from Reader import reader, types, status
from Log import LOG
from Gui import GUI
from Options import options
import datetime
from MapReference import map_ref, subarea_ref, area_ref, superarea_ref
import House
import Roleplay
import Elements
import Fight
from i18n import i18n_fr

class Map():
    def __init__(self):
        self.x = None
        self.y = None
        self.name = None
        self.actors = []
        self.interactive_elements = []
        self.stated_elements = []
        self.house_details = []
        self.obstacles = []
        self.fights = []
        return

    def to_json(self):
        data = {
            'x': self.x,
            'y': self.y,
            'name': self.name
        }
        return data

    def parse_map(self):
        self.id = reader.readDouble()
        self.key = reader.readString()

    def parse_map_complementary_infos(self):
        self.sub_area_id = reader.readVarUhShort()
        self.map_id = reader.readDouble()
        self.x, self.y, self.name = get_coords(self.map_id)
        LOG.info(f"Map [{self.x},{self.y}] - {self.name}")
        self.houses_number = reader.readUnsignedShort()
        self.house_details = []
        for i in range(0, self.houses_number):
            typev = reader.readType()
            if typev == "HouseInformations;":
                self.house_details.append(House.HouseInformations())
            elif typev == "AccountHouseInformations;":
                self.house_details.append(House.AccountHouseInformations())
            elif typev == "HouseInformationsInside;":
                self.house_details.append(House.HouseInformationsInside())
            elif typev == "HouseInformationsForGuild;":
                self.house_details.append(House.HouseInformationsForGuild())
            elif typev == "HouseOnMapInformations;":
                self.house_details.append(House.HouseOnMapInformations())
            elif typev == "HouseInstanceInformations;":
                self.house_details.append(House.HouseInstanceInformations())
            elif typev == "HouseGuildedInformations;":
                self.house_details.append(House.HouseGuildedInformations())
            else:
                LOG.error(f"Unhandled type {typev} for HouseInformations")
        self.actors_len = reader.readUnsignedShort()
        self.actors = []
        for i in range(0, self.actors_len):
            typev = reader.readType()
            if typev == "GameRolePlayNamedActorInformations;":
                self.actors.append(Roleplay.GameRolePlayNamedActorInformations())
            elif typev == "GameRolePlayActorInformations;":
                self.actors.append(Roleplay.GameRolePlayActorInformations())
            elif typev == "GameRolePlayCharacterInformations;":
                self.actors.append(Roleplay.GameRolePlayCharacterInformations())
            elif typev == "GameRolePlayGroupMonsterInformations;":
                self.actors.append(Roleplay.GameRolePlayGroupMonsterInformations())
            elif typev == "GameRolePlayTaxCollectorInformations;":
                self.actors.append(Roleplay.GameRolePlayTaxCollectorInformations())
            elif typev == "GameRolePlayNpcInformations;":
                self.actors.append(Roleplay.GameRolePlayNpcInformations())
            elif typev == "GameRolePlayNpcWithQuestInformations;":
                self.actors.append(Roleplay.GameRolePlayNpcWithQuestInformations())
            elif typev == "GameRolePlayMerchantInformations;":
                self.actors.append(Roleplay.GameRolePlayMerchantInformations())
            elif typev == "GameRolePlayMountInformations;":
                self.actors.append(Roleplay.GameRolePlayMountInformations())
            elif typev == "GameRolePlayPrismInformations;":
                self.actors.append(Roleplay.GameRolePlayPrismInformations())
            elif typev == "GameRolePlayTreasureHintInformations;":
                self.actors.append(Roleplay.GameRolePlayTreasureHintInformations())
            elif typev == "GameRolePlayGroupMonsterWaveInformations;":
                self.actors.append(Roleplay.GameRolePlayGroupMonsterWaveInformations())
            elif typev == "GameRolePlayPortalInformations;":
                self.actors.append(Roleplay.GameRolePlayPortalInformations())
            elif typev == "GameRolePlayMutantInformations;":
                self.actors.append(Roleplay.GameRolePlayMutantInformations())
            else:
                LOG.error(f"Unhandled type {typev} for GameRolePlayActorInformations")
        self.interactive_elements_len = reader.readUnsignedShort()
        self.interactive_elements = []
        for i in range(0, self.interactive_elements_len):
            typev = reader.readType()
            if typev == "InteractiveElementSkill;":
                self.interactive_elements.append(Elements.InteractiveElementSkill())
            elif typev == "InteractiveElementNamedSkill;":
                self.interactive_elements.append(Elements.InteractiveElementNamedSkill())
            elif typev == "InteractiveElement;":
                self.interactive_elements.append(Elements.InteractiveElement())
            elif typev == "InteractiveElementWithAgeBonus;":
                self.interactive_elements.append(Elements.InteractiveElementWithAgeBonus())
            else:
                LOG.error(f"Unhandled type {typev} for InteractiveElement")
        self.stated_elements_len = reader.readUnsignedShort()
        self.stated_elements = []
        for i in range(0, self.stated_elements_len):
            self.stated_elements.append(Elements.StatedElement())
        self.obstacles_len = reader.readUnsignedShort()
        self.obstacles = []
        for i in range(0, self.obstacles_len):
            self.obstacles.append(Elements.MapObstacle())
        self.fights_len = reader.readUnsignedShort()
        self.fights = []
        for i in range(0, self.fights_len):
            self.fights.append(Fight.FightCommonInformations())
        self.aggressive_monsters = reader.readBoolean()
        self.fight_positions = Fight.FightStartingPositions()

    def add_infos_to_house(self, house_id):
        for h in self.house_details:
            if int(h.house_id) == int(house_id):
                return h

    def print_infos(self):
        GUI.advanced_html = f"On map {self.x}, {self.y}: <br />"
        for actor in self.actors:
            if actor.name == None:
                continue
            if isinstance(actor.name, str):
                name = [actor.name]
            else:
                name = actor.name
            GUI.advanced_html += f"- {name}<br />"
        for fight in self.fights:
            for team in fight.fight_teams:
                for actor in team.team_member:
                    if actor.name == None:
                        continue
                    if isinstance(actor.name, str):
                        name = [actor.name]
                    else:
                        name = actor.name
                    GUI.advanced_html += f"- {name}<br />"


    def handle_interactive_element(self, element_ref):
        for elem in self.interactive_elements:
            if elem.element_id == element_ref.element_id:
                string = "ON"
                if len(element_ref.enabled_skills) == 0:
                    string = "OFF"
                if elem.last_timer == -1:
                    timestring = ""
                else:
                    timestring = (datetime.datetime.now() - elem.last_timer).total_seconds()
                elem.last_timer = datetime.datetime.now()
                #LOG.info(f"{elem.element_id} {string} {str(datetime.datetime.now())[11:]} {str(timestring)}")


    def check_looking_for(self, bonus_npc=None):
        self.names_on_map = []
        self.id_on_map = []
        found = []
        for actor in self.actors:
            self.id_on_map.append(actor.id)
            if actor.name == None:
                continue
            if isinstance(actor.name, str):
                self.names_on_map.append(actor.name)
            else:
                for n in actor.name:
                    self.names_on_map.append(n)
        for fight in self.fights:
            for team in fight.fight_teams:
                for actor in team.team_member:
                    self.names_on_map.append(actor.name)
        for val in self.names_on_map:
            if val.upper() in options.looking_for:
                #LOG.display(f"Found {val} on map [{self.x}, {self.y}]")
                found.append(val)
        if bonus_npc != None:
            for val in self.id_on_map:
                if int(val) == int(bonus_npc):
                    return 1
        return 0

def get_coords(map_id):
    x = 0
    y = 0
    name = ""
    for m in map_ref.data:
        if int(m['id']) == int(map_id):
            name = get_full_name(m)
            x = m['posX']
            y = m['posY']
    return (int(x), int(y), name)

def get_full_name(m):
    val = []
    sub = None
    area = None
    sup = None
    name = ""
    if m['nameId'] != 0:
        name += i18n_fr.get_name(m['nameId'])
        val.append(i18n_fr.get_name(m['nameId']))
    sub = subarea_ref.get_map_by_id(m['subAreaId'])
    if sub is not None:
        if len(name) > 0:
            name += " - "
        name += i18n_fr.get_name(sub['nameId'])
        if sub['nameId'] != 0:
            val.append(i18n_fr.get_name(sub['nameId']))
        area = area_ref.get_map_by_id(sub['areaId'])
    if area is not None:
        if len(name) > 0:
            name += " - "
        name += i18n_fr.get_name(area['nameId'])
        if area['nameId'] != 0:
            val.append(i18n_fr.get_name(area['nameId']))
        sup = superarea_ref.get_map_by_id(area['superAreaId'])
    return name
