from core.ui import DialogUi

from siege import game, Locale
from siege.util import PixelRect, Vector


class TooltipUi(DialogUi):
    def __init__(self, player):
        self.player = player
        DialogUi.__init__(self, 'tooltip', PixelRect(0, 0, 300, 500))
        self.load('html/tooltip.html')
        self.view.show()
        self.targetView = None
        self.area = PixelRect()
        self.view.register('showTooltip', self.onShow)
        self.view.register('onResize', self.onResize)
        self.size = Vector()

        #Setup Feature Icons
        self.featureIcons = {}
        for feature in ["Block", "Consumable", "Inventory", "Material", "Placeable", "Researchable", "Surface", "Tool"]:
            self.featureIcons[feature] = "../images/item-{}.png".format(feature.lower())

    def update(self, frameTime):
        if self.size.x != 0:
            if not self.view.isVisible():
                self.view.show()
            mousePosition = game.getMousePosition()
            if self.area.contains(mousePosition) and self.targetView.isVisible():
                position = Vector(mousePosition.x - 4, mousePosition.y - 12)
                windowSize = game.render.getWindowSize()
                if position.x + self.size.x > windowSize.x:
                    position.x -= self.size.x - 14
                if position.y + self.size.y + 30 > windowSize.y:
                    position.y -= self.size.y + 16
                self.view.setPosition(position)
            else:
                self.onHide()

    def onResize(self, view, args):
        self.size.x = args[1].toInteger()
        self.size.y = args[2].toInteger()

    def onShow(self, view, args):
        #onShow is called when player does mouseover on item
        commands = []
        commands.append("App.tooltip.beginPropertyChanges();")
        self.cleanTooltip(commands)
        #Compose the tooltip based off of the type
        #There are multiple parts to a tooltip any can be ignored
        #Header Info (Image, Name and Description)
        #Weapon Info (Weapon Category)
        #Equipment Info (Attributes, Rarity, Quality)
        tooltipType = args[1].toString()
        if tooltipType == "item":
            entityId = args[3].toInteger()
            contentId = args[4].toInteger()

            #If this is an empty item that means the tooltip changed from under the mouse. Hide the tooltip.
            if contentId == 0:
                self.onHide()
                return

            contentEntity = game.content.get(contentId).entity
            entity = game.entity.get(entityId) if entityId else contentEntity
            if not entity:
                return
            isEquipment = entity.has('equipment')
            if entity.has('item'):
                # Do not set name if is equipment since that will set it
                name = '' if isEquipment else entity.name
                description = contentEntity.item.description
                description = Locale.getEscaped(description) if Locale.has(description) else ""
                self.setHeader(commands, name, description, contentEntity.item.flavor, entity.render.getIconPath())
                commands.append("App.tooltip.features.clear();")
                for feature in self.getItemFeatures(entity):
                    commands.append("App.tooltip.features.pushObject(App.Feature.create({{'icon': '{}'}}));".format(self.featureIcons[feature]))
            if entity.has('weapon'):
                self.setWeapon(commands, entity.weapon)
            if entity.has('tool'):
                self.setTool(commands, entity.tool)
            if isEquipment:
                self.setEquipment(commands, entity.equipment)
        elif tooltipType == "effect":
            effectName = args[3].toString()
            effect = game.effects.get(effectName)
            self.setHeader(commands, effect.name, Locale.getEscaped(effect.description), "", effect.icon)
        elif tooltipType == "skill":
            talentName = args[3].toString()
            skillName = args[4].toString()
            increaseLevel = args[5].toBoolean()
            skill = self.player.entity.talents.get(talentName).get(skillName)
            skillLevel = max(skill.level, 1)
            if skill.level > 0 and increaseLevel:
                skillLevel += 1
            self.setHeader(commands, skill.name, skill.description(skillLevel), "", skill.icon)
            commands.append("App.tooltip.set('level', '{}');".format(Locale.getEscaped("TooltipSkillLevel").format(skillLevel)))
        elif tooltipType == "simple":
            description = args[3].toString()
            commands.append("App.tooltip.set('description', '{0}');".format(description))
        elif tooltipType == "hide":
            self.onHide()
            return

        #Update tooltip area. Mouse out of this area and tooltip is hidden.
        position = view.getPosition()
        areaJs = args[2].toObject()
        self.area.x = areaJs.getProperty('x').toInteger() + int(position.x)
        self.area.y = areaJs.getProperty('y').toInteger() + int(position.y)
        self.area.width = areaJs.getProperty('width').toInteger()
        self.area.height = areaJs.getProperty('height').toInteger()

        commands.append("App.tooltip.endPropertyChanges();")
        commands.append("App.tooltip.show();")
        self.view.execute(commands)
        self.view.waitForRefresh()
        self.targetView = view
        self.update(0)

    def onHide(self):
        #onHide is called when player does mouseout on item
        commands = []
        commands.append("App.tooltip.beginPropertyChanges();")
        self.cleanTooltip(commands)
        commands.append("App.tooltip.endPropertyChanges();")
        commands.append("$('.window-container').hide();")
        self.view.execute(commands)
        self.size.x = 0
        self.hide()

    def cleanTooltip(self, commands):
        commands.append("App.tooltip.set('name', '');")
        commands.append("App.tooltip.set('description', '');")
        commands.append("App.tooltip.set('flavor', '');")
        commands.append("App.tooltip.set('slot', '');")
        commands.append("App.tooltip.set('isTool', false);")
        commands.append("App.tooltip.set('weapon', '');")
        commands.append("App.tooltip.set('power', 0);")
        commands.append("App.tooltip.set('image', '');")
        commands.append("App.tooltip.set('quality', 0);")
        commands.append("App.tooltip.set('level', '');")
        commands.append("App.tooltip.set('underLevel', false);")
        commands.append("App.tooltip.attributes.clear();")
        commands.append("App.tooltip.features.clear();")

    def setHeader(self, commands, name, description, flavor, image):
        if name:
            commands.append("App.tooltip.set('name', '{}');".format(Locale.getEscaped(name)))
        commands.append("App.tooltip.set('description', '{}');".format(description))
        commands.append("App.tooltip.set('flavor', '{}');".format(Locale.getEscaped(flavor)) if Locale.has(flavor) else "")
        commands.append("App.tooltip.set('image', 'asset://crea/{}');".format(image))

    def setWeapon(self, commands, weapon):
        commands.append("App.tooltip.set('weapon', '{}');".format(Locale.get(weapon.category)))
        commands.append("App.tooltip.set('power', {});".format(weapon.power))

    def setTool(self, commands, tool):
        commands.append("App.tooltip.set('isTool', true);")
        commands.append("App.tooltip.set('power', {});".format(tool.power))

    def setEquipment(self, commands, equipment):
        commands.append("App.tooltip.set('name', '{}');".format(equipment.getModifiedName()))
        commands.append("App.tooltip.set('slot', '{}');".format(Locale.get(equipment.getSlot())))
        commands.append("App.tooltip.set('quality', {});".format(equipment.quality))
        if equipment.levelRequired:
            commands.append("App.tooltip.set('level', '{}');".format(Locale.getEscaped("TooltipLevelRequired").format(equipment.levelRequired)))
            underLevel = equipment.levelRequired > self.player.entity.combat.level.get()
            commands.append("App.tooltip.set('underLevel', {});".format(str(underLevel).lower()))
        commands.append("App.tooltip.attributes.clear();")
        for attribute in equipment.getAttributes():
            commands.append("App.tooltip.attributes.pushObject(App.Attribute.create({{text: '{}'}}));".format(attribute.text))

    def getItemFeatures(self, entity):
        #["Consumable", "Material"]
        features = [f for f in entity.item.features]
        if entity.has('tool'):
            features.append("Tool")
        if entity.has('tile'):
            features.append("Block")
        if entity.has('bag') and entity.bag.canCarry:
            features.append("Inventory")
        if entity.has('placement'):
            features.append("Placeable")
        if entity.has('surface'):
            features.append("Surface")
        if not entity.item.isUnique and entity.content.id in game.research.materials:
            features.append("Material")
            researchCount = len(self.player.entity.research.materials.get(entity.content.id, []))
            totalCount = len(game.research.materials[entity.content.id])
            if researchCount < totalCount:
                features.append("Researchable")
        return features
