import math

from core.helper import getRandomPath
from core.talent import chanceToGainTalentPoints

from siege import game, InventoryItem, ToolItem
from siege.component import ToolbarSlot
from siege.network import NetworkManager
from siege.util import Random, Sizes, Vector
from siege.world import World
from siege.world.realm import WaterCell


def playerCreated(player):
    bagEntity = game.content.get("bag").entity
    for index in xrange(2):
        player.entity.inventory.addBag(index, bagEntity)
    for talent in player.entity.talents.ordered:
        for skill in talent.getSkills():
            if skill.getCost() == 0:
                talent.purchaseSkill(player, skill)


def handlePlayerSpawn(player):
    realm = player.entity.realm
    area = realm.startArea
    position = Vector(area.x + Random.get(int(area.width)), area.y)
    player.entity.setPosition(position)
    travel = game.travel
    startCrystal = None
    for crystal in travel.loadedCrystals.keys():
        if position.getDistance(crystal.getPosition(), realm.size.width) < 50:
            startCrystal = crystal
            break
    if startCrystal:
        travel.activateCrystal(player, crystal)
        travel.attuneCrystal(player, crystal)


def playerJoined(player):
    research = player.entity.research
    if not research.recipes:
        recipes = ["lumber",
                   "paper",
                   "torch",
                   "research_desk",
                   "makeshift_tool",
                   "wood_club"
                   ]
        for recipe in recipes:
            research.learnRecipe(recipe)
    inventory = player.entity.inventory
    toolbar = player.entity.toolbar
    #Return if they player has any items in his inventory
    for bag in inventory.getBags():
        if bag and not bag.isEmpty():
            return
    #No items! Lets give him some!
    items = [("makeshift_tool", 1, 0),
             ("wood_club", 1, 2),
             ]
    for item in items:
        content = game.content.get(item[0])
        inventoryItem = InventoryItem(content, item[1])
        if inventoryItem.entity.item.isUnique:
            if inventoryItem.entity.has('equipment'):
                inventoryItem.entity = game.equipment.create(content, Random.get(40, 80))
            else:
                inventoryItem.entity = game.entity.create(content)
        if inventory.canAdd(inventoryItem.entity):
            inventory.add(inventoryItem.entity, item[1])
            if item[2] >= 0:
                toolbar.set(item[2], ToolbarSlot.LEFT, ToolItem(inventoryItem))
    #Set Collect skill on toolbar
    gatherTalent = player.entity.talents.gather
    toolbar.set(1, ToolbarSlot.LEFT, ToolItem(gatherTalent, gatherTalent.get("Collect")))
    divineTalent = player.entity.talents.divine
    toolbar.set(3, ToolbarSlot.LEFT, ToolItem(divineTalent, divineTalent.get("Heal")))
    arcaneTalent = player.entity.talents.arcane
    toolbar.set(4, ToolbarSlot.LEFT, ToolItem(arcaneTalent, arcaneTalent.get("Fire")))


def craftFinish(player, results, craft, count, result, item, remainder):
    level = craft.level
    rate = int(min(30 * math.sqrt(float(count)), 100))
    amount = craft.experience * (level / 5 + 1) * min(count, math.sqrt(count) * 2)
    chanceToGainTalentPoints(player, player.entity.talents.craft, level, rate, amount)
    #Handle Remainder
    if remainder:
        position = player.entity.physics.getCenter()
        player.entity.realm.dropped.create(InventoryItem(item.content, remainder), position, Vector(Random.get(-2.0, 2.0), -6))


def hitTile(entity, realm, tile, layer, tilePosition, brokeTile):
    if brokeTile:
        player = World.get().getPlayer(entity)
        if player:
            chanceToGainTalentPoints(player, entity.talents.gather, tile.level, rate=20, amount=15)
    sound = tile.getOnBreakSound() if brokeTile else tile.getOnHitSound()
    if sound:
        worldPos = tilePosition.getWorld()
        position = Vector(worldPos.x * Sizes.TILE, worldPos.y * Sizes.TILE)
        game.audio.playAt(getRandomPath(sound), position, broadcast=True)


def handleWaterPhysics(entities, time):
    for entity in entities:
        physics = entity.physics
        if physics.sleeping:
            continue
        body = physics.getWorldBody()
        body.y += body.height / 2
        body.height /= 2
        cells = World.get().getRealm().automata.getCells(body)
        if cells:
            amount = 0
            for cell in cells:
                if isinstance(cell, WaterCell):
                    amount += cell.quantity
            maxAmount = int(body.width / Sizes.SUBTILE) * int(body.height / Sizes.SUBTILE) * cells[0].getMaxQuantity()
            percentage = amount / maxAmount
            if percentage > 0.4:
                if entity.has('descent'):
                    entity.descent.reset()
                velocity = physics.getVelocity()
                slow = 1.0 - (0.35 * percentage)
                velocity.x *= slow
                velocity.y *= slow
                physics.setVelocity(velocity)
                if not physics.jumpTimer.expired():
                    physics.jumpTimer += time - (time / 2)


def disableMonsters(world):
    game.spawner.enabled = False


def register():
    game.events["player_created"].listen(playerCreated)
    game.events["perform_physics"].listen(handleWaterPhysics)
    if NetworkManager.isHost():
        game.events["player_spawn"].listen(handlePlayerSpawn)
        game.events["player_joined"].listen(playerJoined)
        game.events["craft_finish"].listen(craftFinish)
        game.events["hit_tile"].listen(hitTile)
        # game.events["world_loaded"].listen(disableMonsters)


def unregister():
    game.events["player_created"].remove(playerCreated)
    game.events["perform_physics"].remove(handleWaterPhysics)
    game.events["player_spawn"].remove(handlePlayerSpawn)
    game.events["player_joined"].remove(playerJoined)
    game.events["craft_finish"].remove(craftFinish)
    game.events["hit_tile"].remove(hitTile)
