from Reader import reader, types, status
from pprint import pprint
from Log import LOG
from Gui import GUI
from i18n import i18n_fr
import utils
import json
from Monster import monsters_ref
import FightResult
import pdb
import Alliance
import Server

class FightStartingPositions():
    def __init__(self):
        self.challengers_pos_len = reader.readShort()
        self.challengers_pos = []
        for i in range(0, self.challengers_pos_len):
            self.challengers_pos.append(reader.readVarUhShort())
        self.defenders_pos_len = reader.readShort()
        self.defenders_pos = []
        for i in range(0, self.defenders_pos_len):
            self.defenders_pos.append(reader.readVarUhShort())

class FightOptionsInformations():
    def __init__(self):
        self.boxed_infos = reader.readByte()

class FightTeamMemberInformations():
    def __init__(self):
        self.name = None
        self.id = reader.readDouble()
        return

class FightTeamMemberTaxCollectorInformations(FightTeamMemberInformations):
    def __init__(self):
        super().__init__()
        self.first_name_id = reader.readVarUhShort()
        self.last_name_id = reader.readVarUhShort()
        self.name = f"{self.first_name_id} {self.last_name_id}"
        self.level = reader.readUnsignedByte()
        self.guild_id = reader.readVarUhInt()
        self.uid = reader.readDouble()

class FightTeamMemberEntityInformation(FightTeamMemberInformations):
    def __init__(self):
        super().__init__()
        self.model_id = reader.readByte()
        self.level = reader.readVarUhShort()
        self.master_id = reader.readDouble()

class FightTeamMemberCharacterInformations(FightTeamMemberInformations):
    def __init__(self):
        super().__init__()
        self.name = reader.readString()
        self.level = reader.readVarUhShort()

class FightTeamMemberMonsterInformations(FightTeamMemberInformations):
    def __init__(self):
        super().__init__()
        self.monster_id = reader.readInt()
        for i in monsters_ref.data:
            if i["id"] == self.monster_id:
                self.name = i18n_fr.get_name(str(i['nameId']))
        self.grade = reader.readByte()

class FightTeamMemberWithAllianceCharacterInformations(FightTeamMemberCharacterInformations):
    def __init__(self):
        super().__init__()
        self.alliance_infos = Alliance.BasicAllianceInformations()

class AbstractFightTeamInformations():
    def __init__(self):
        self.team_id = reader.readByte()
        self.leader_id = reader.readDouble()
        self.team_side = reader.readByte()
        self.team_type_id = reader.readByte()
        self.nb_waves = reader.readByte()
        return

class FightTeamInformations(AbstractFightTeamInformations):
    def __init__(self):
        super().__init__()
        self.team_member = []
        self.team_member_len = reader.readUnsignedShort()
        for i in range(0, self.team_member_len):
            typev = reader.readType()
            if typev == "FightTeamMemberInformations;":
                self.team_member.append(FightTeamMemberInformations())
            elif typev == "FightTeamMemberCharacterInformations;":
                self.team_member.append(FightTeamMemberCharacterInformations())
            elif typev == "FightTeamMemberEntityInformation;":
                self.team_member.append(FightTeamMemberEntityInformation())
            elif typev == "FightTeamMemberMonsterInformations;":
                self.team_member.append(FightTeamMemberMonsterInformations())
            elif typev == "FightTeamMemberWithAllianceCharacterInformations;":
                self.team_member.append(FightTeamMemberWithAllianceCharacterInformations())
            elif typev ==    "FightTeamMemberTaxCollectorInformations;":
                self.team_member.append(FightTeamMemberTaxCollectorInformations())
            else:
                LOG.error(f"Unhandled type {typev} for FightTeamInformations")
        return

class FightCommonInformations():
    def __init__(self):
        self.fight_id = reader.readVarUhShort()
        self.fight_type = reader.readByte()
        self.fight_teams_len = reader.readUnsignedShort()
        self.fight_teams = []
        for i in range(0, self.fight_teams_len):
            typev = reader.readType()
            if typev == "FightTeamInformations;":
                self.fight_teams.append(FightTeamInformations())
            else:
                LOG.error(f"Unhandled type {typev} for FightCommonInformations")
        self.fight_teams_positions_len = reader.readUnsignedShort()
        self.fight_teams_positions = []
        for i in range(0, self.fight_teams_positions_len):
            self.fight_teams_positions.append(reader.readVarUhShort())
        self.fight_teams_options_len = reader.readUnsignedShort()
        self.fight_teams_options = []
        for i in range(0, self.fight_teams_options_len):
            self.fight_teams_options.append(FightOptionsInformations())

class FightEnd():
    def __init__(self, curr_map):
        self.data = []
        self.combat_parse = -1
        self.duration = reader.readInt()
        self.reward_rate = reader.readVarShort()
        self.loot_share_limit = reader.readShort()
        self.map = curr_map.to_json()
        self.med_level = [0, 0]
        self.nb_players = [0, 0]
        self.results = []
        self.teams = []
        length = reader.readUnsignedShort()
        for _ in range(0, length):
            typev = reader.readType()
            if typev == "FightResultListEntry;":
                self.results.append(FightResult.FightResultListEntry())
            elif typev == "FightResultFighterListEntry;":
                self.results.append(FightResult.FightResultFighterListEntry())
            elif typev == "FightResultTaxCollectorListEntry;":
                self.results.append(FightResult.FightResultTaxCollectorListEntry())
            elif typev == "FightResultPlayerListEntry;":
                self.results.append(FightResult.FightResultPlayerListEntry())
            elif typev == "FightResultMutantListEntry;":
                self.results.append(FightResult.FightResultMutantListEntry())
            else:
                LOG.error(f"Unhandled type {typev} for FightEnd")
        length = reader.readUnsignedShort()
        for _ in range(0, length):
            self.teams.append(NamedTeamWithOutcome())
        self.hash = 0
        for item in self.results:
            self.hash += item.hash()
        self.hash += self.duration

    def generate_data(self):
        self.data = {
            'id': self.hash,
            "winner": self.results[0].winner(),
            'duration': self.duration,
            'combat_parse_status': self.combat_parse,
            'med_level': self.med_level,
            'nb_players': self.nb_players,
            'teams': [[], []],
            'map': self.map
        }
        for player in self.results:
            if player.is_player == True:
                p_data = {
                    'is_player': True,
                    'loot': player.rewards.to_list(),
                    'kamas': player.rewards.kamas,
                    'team': player.team,
                    'user_id': player.id,
                    'level': player.level,
                    'username': player.name,
                    'monster_id': -1,
                    'damage': player.damage,
                    'alive': player.alive,
                    'sex': int(player.sex),
                    'breed_id': player.breed_id
                }
            else:
                p_data = {
                    'is_player': False,
                    'loot': [],
                    'kamas': 0,
                    'team': player.team,
                    'user_id': -1,
                    'level': player.level,
                    'username': player.name,
                    'monster_id': player.gid,
                    'damage': player.damage,
                    'alive': player.alive,
                    'sex': int(player.sex),
                    'breed_id': player.breed_id
                }
            self.data['teams'][player.team].append(p_data)
        LOG.info(f"Combat ended after {int(self.duration / 1000 / 60)} minutes.")

class NamedTeamWithOutcome():
    def __init__(self):
        self.team = NamedTeam()
        self.outcome = reader.readVarUhShort()

class NamedTeam():
    def __init__(self):
        self.team_id = reader.readByte()
        self.team_name = reader.readString()
