from Reader import reader, types, status
from Log import LOG
import os
import json
from i18n import i18n_fr
from MonstersReference import monsters_ref

class ActorRestrictionsInformations():
    def __init__(self):
        self.boxed_info_0 = reader.readByte()
        self.boxed_info_1 = reader.readByte()
        self.boxed_info_2 = reader.readByte()


class SubEntity():
    def __init__(self):
        self.binding_point_categ = reader.readByte()
        self.binding_point_func = reader.readByte()
        self.appearance = EntityLook()

class ActorAlignmentInformations():
    def __init__(self):
        self.alignment_side = reader.readByte()
        self.alignment_value = reader.readByte()
        self.alignment_grade = reader.readByte()
        self.character_power = reader.readDouble()
        return

class ActorExtendedAlignmentInformations(ActorAlignmentInformations):
    def __init__(self):
        super().__init__()
        self.honor = reader.readVarUhShort()
        self.honor_grade_floor = reader.readVarUhShort()
        self.honor_next_grade_floor = reader.readVarUhShort()
        self.aggressable = reader.readByte()

class FighterMinimalStats():
    def __init__(self):
        return

class EntityLook():
    def __init__(self):
        self.bones_id = reader.readVarUhShort()
        self.skin_length = reader.readUnsignedShort()
        self.skins = []
        self.colors = []
        self.scales = []
        self.subentities = []
        for i in range(0, self.skin_length):
            tmp = reader.readVarUhShort()
            self.skins.append(tmp)
        self.color_len = reader.readUnsignedShort()
        for i in range(0, self.color_len):
            tmp = reader.readInt()
            self.colors.append(tmp)
        self.scales_len = reader.readUnsignedShort()
        for i in range(0, self.scales_len):
            tmp = reader.readVarShort()
            self.scales.append(tmp)
        self.subentities_len = reader.readUnsignedShort()
        for i in range(0, self.subentities_len):
            tmp = SubEntity()
            self.subentities.append(tmp)

class IndexedEntityLook():
    def __init__(self):
        self.look = EntityLook()
        self.index = reader.readByte()

class PlayerStatus():
    def __init__(self):
        self.status = reader.readByte()

class EntityDispositionInformations():
    def __init__(self):
        self.cell_id = reader.readShort()
        self.direction = reader.readByte()

class FightEntityDispositionInformations(EntityDispositionInformations):
    def __init__(self):
        super().__init__()
        self.carrying_character_id = reader.readDouble()
        return

class ContextActorPositionInformations():
    def __init__(self):
        self.contextual_id = reader.readDouble()
        self.name = None
        typev = reader.readType()
        if typev == "FightEntityDispositionInformations;":
            self.fight_entity_disp = FightEntityDispositionInformations()
        elif typev == "EntityDispositionInformations;":
            self.fight_entity_disp = EntityDispositionInformations()
        else:
            LOG.error(f"Unhandled type {typev} for ContextActorPositionInformations")

class ContextActor(ContextActorPositionInformations):
    def __init__(self):
        super().__init__()
        self.appearance = EntityLook()

class ContextBasicSpawnInformations():
    def __init__(self):
        self.team_id = reader.readByte()
        self.alive = reader.readBoolean()
        typev = reader.readType()
        if typev == "GameContextActorPositionInformations;":
            self.context_actor_info = ContextActorPositionInformations()
        else:
            LOG.error(f"Unhandled type {typev} for ContextActor")
        return

class CharacterCharacteristic():
    def __init__(self):
        self.id = reader.readShort()

class CharacterCharacteristicDetailed(CharacterCharacteristic):
    def __init__(self):
        super().__init__()
        self.base = reader.readVarShort()
        self.additionnal = reader.readVarShort()
        self.items_mount_bonus = reader.readVarShort()
        self.alignment_gift = reader.readVarShort()
        self.context_modif = reader.readVarShort()

class CharacterCharacteristicValue(CharacterCharacteristic):
    def __init__(self):
        super().__init__()
        self.total = reader.readInt()

class CharacterCharacteristics():
    def __init__(self):
        self.characteristics = []
        length = reader.readUnsignedShort()
        for i in range(0, length):
            typev = reader.readType()
            if typev == "CharacterCharacteristic;":
                self.characteristics.append(CharacterCharacteristic())
            elif typev == "CharacterCharacteristicDetailed;":
                self.characteristics.append(CharacterCharacteristicDetailed())
            elif typev == "CharacterCharacteristicValue;":
                self.characteristics.append(CharacterCharacteristicValue())
            else:
                LOG.error(f"Unhandled type {typev} for CharacterCharacteristics")

class CharacterCharacteristicsInformations():
    def __init__(self):
        self.experience = reader.readVarUhLong()
        self.exp_floor = reader.readVarUhLong()
        self.exp_next_floor = reader.readVarUhLong()
        self.exp_bonus_limit = reader.readVarUhLong()
        self.kamas = reader.readVarUhLong()
        self.alignment = ActorExtendedAlignmentInformations()
        self.crit_weapon = reader.readVarUhShort()
        self.characteristics = []
        for _ in range(0, reader.readUnsignedShort()):
            typev = reader.readType()
            if typev == "CharacterCharacteristic;":
                self.characteristics.append(CharacterCharacteristic())
            elif typev == "CharacterCharacteristicDetailed;":
                self.characteristics.append(CharacterCharacteristicDetailed())
            elif typev == "CharacterCharacteristicValue;":
                self.characteristics.append(CharacterCharacteristicValue())
            else:
                LOG.error(f"Unhandled type {typev} for CharacterCharacteristicsInformations")
        #NOT FINISHED
        

class FightCharacteristics():
    def __init__(self):
        self.infos = CharacterCharacteristics()
        self.summoner = reader.readDouble()
        self.summoned = reader.readBoolean()
        self.invis = reader.readByte()

class FightMinimalStats():
    def __init__(self):
        self.life_points = reader.readVarUhInt()
        self.max_life_points = reader.readVarUhInt()
        self.base_max_life_points = reader.readVarUhInt()
        self.permanent_damage_percent = reader.readVarUhInt()
        self.shield_points = reader.readVarUhInt()
        self.action_points = reader.readVarShort()
        self.max_action_points = reader.readVarShort()
        self.movement_points = reader.readVarShort()
        self.max_movement_points = reader.readVarShort()
        self.summoner = reader.readDouble()
        self.summoned = reader.readBoolean()
        self.neutral_element_resist_percent = reader.readVarShort()
        self.earth_element_resist_percent = reader.readVarShort()
        self.water_element_resist_percent = reader.readVarShort()
        self.air_element_resist_percent = reader.readVarShort()
        self.fire_element_resist_percent = reader.readVarShort()
        self.neutral_element_reduction = reader.readVarShort()
        self.earth_element_reduction = reader.readVarShort()
        self.water_element_reduction = reader.readVarShort()
        self.air_element_reduction = reader.readVarShort()
        self.fire_element_reduction = reader.readVarShort()
        self.critical_damage_fixed_resist = reader.readVarShort()
        self.push_damage_fixed_resist = reader.readVarShort()
        self.pvp_neutral_element_resist_percent = reader.readVarShort()
        self.pvp_earth_element_resist_percent = reader.readVarShort()
        self.pvp_water_element_resist_percent = reader.readVarShort()
        self.pvp_air_element_resist_percent = reader.readVarShort()
        self.pvp_fire_element_resist_percent = reader.readVarShort()
        self.pvp_neutral_element_reduction = reader.readVarShort()
        self.pvp_earth_element_reduction = reader.readVarShort()
        self.pvp_water_element_reduction = reader.readVarShort()
        self.pvp_air_element_reduction = reader.readVarShort()
        self.pvp_fire_element_reduction = reader.readVarShort()
        self.dodge_PA_lost_probability = reader.readVarUhShort()
        self.dodge_PM_lost_probability = reader.readVarUhShort()
        self.tackleBlock = reader.readVarShort()
        self.tackleEvade = reader.readVarShort()
        self.fixed_damage_reflection = reader.readVarShort()
        self.invisibility_state = reader.readByte()
        self.melee_damage_received_percent = reader.readVarUhShort()
        self.ranged_damage_received_percent = reader.readVarUhShort()
        self.weapon_damage_received_percent = reader.readVarUhShort()
        self.spell_damage_received_percent = reader.readVarUhShort()
        attrs = vars(self)

class FightMinimalStatsPreparation(FightMinimalStats):
    def __init__(self):
        super().__init__()
        self.initiative = reader.readVarUhInt()

class FightFighterInformations(ContextActor):
    def __init__(self):
        super().__init__()
        self.spawn_info = ContextBasicSpawnInformations()
        self.fight_wave = reader.readByte()
        typev = reader.readType()
        if typev == "GameFightMinimalStatsPreparation;":
            self.stats = FightMinimalStatsPreparation()
        elif typev == "GameFightMinimalStats;":
            self.stats = FightMinimalStats()
        elif typev == "GameFightCharacteristics;":
            self.stats = FightCharacteristics()
        else:
            LOG.error(f"Unhandled type {typev} for FightFighterInformations")
        self.previous_pos_len = reader.readUnsignedShort()
        self.previous_pos = []
        for i in range(0, self.previous_pos_len):
            self.previous_pos.append(reader.readVarUhShort())

class FightTaxCollectorInformations(FightFighterInformations):
    def __init__(self):
        super().__init__()
        self.f_name_id = reader.readVarUhShort()
        self.l_name_id = reader.readVarUhShort()
        self.name = f"{self.f_name_id} {self.l_name_id}"

class FightFighterNamedInformations(FightFighterInformations):
    def __init__(self):
        super().__init__()
        self.name = reader.readString()
        self.status = PlayerStatus()
        self.league_id = reader.readVarShort()
        self.ladder_position = reader.readInt()
        self.hidden_in_prefight = reader.readBoolean()


class FightMonsterInformations(FightFighterInformations):
    def __init__(self):
        super().__init__()
        self.player = False
        self.breed = 0
        self.creature_generic_id = reader.readVarUhShort()
        for i in monsters_ref.data:
            if i["id"] == self.creature_generic_id:
                self.name = i18n_fr.get_name(str(i['nameId']))
        self.creature_grade = reader.readByte()
        self.capped_level = reader.readShort()
        self.level = self.capped_level
        return

class FightMutantInformation(FightFighterNamedInformations):
    def __init__(self):
        super().__init__()
        self.power_level = reader.readByte()

class FightCharacterInformations(FightFighterNamedInformations):
    def __init__(self):
        super().__init__()
        self.player = True
        self.level = reader.readVarUhShort()
        self.capped_level = 200 if self.level > 200 else self.level
        self.alignmentInfos = ActorAlignmentInformations()
        self.breed = reader.readByte()
        self.sex = reader.readBoolean()
        return

class FightEntityInformation(FightFighterInformations):
    def __init__(self):
        super().__init__()
        self.name = "Compagnon"
        self.entity_model_id = reader.readByte()
        self.level = reader.readVarUhShort()
        self.master_id = reader.readDouble()

class FightShowFighterInformations():
    def __init__(self):
        self.name = None
        typev = reader.readType()
        if typev == "GameFightCharacterInformations;":
            self.entity = FightCharacterInformations()
        elif typev == "GameFightMonsterInformations;":
            self.entity = FightMonsterInformations()
        elif typev == "GameFightTaxCollectorInformations;":
            self.entity = FightTaxCollectorInformations()
        elif typev == "GameFightEntityInformation;":
            self.entity = FightEntityInformation()
        elif typev == "GameFightMutantInformations;":
            self.entity = FightMutantInformation()
        else:
            LOG.error(f"Unhandled type {typev} for FightShowFighterInformations")
        return

def parse_actor():
    #reader.dump_message()
    actor = None
    actor = FightShowFighterInformations()
    return actor

class BaseSpawnMonsterInformation():
    def __init__(self):
        self.creature_generic_id = reader.readVarUhShort()
        self.contextual_id = 0
        self.stats = None
        self.name = self.creature_generic_id
        for i in monsters_ref.data:
            if i["id"] == self.creature_generic_id:
                self.name = i18n_fr.get_name(str(i['nameId']))

class SpawnInformation():
    def __init__(self):
        pass

class SpawnMonsterInformation(BaseSpawnMonsterInformation):
    def __init__(self):
        super().__init__()
        self.grade = reader.readByte()

class SpawnScaledMonsterInformation(BaseSpawnMonsterInformation):
    def __init__(self):
        super().__init__()
        self.level = reader.readShort()

class SpawnCharacterInformation(SpawnInformation):
    def __init__(self):
        super().__init__()
        self.name = reader.readString()
        self.contextual_id = 0
        self.level = reader.readVarUhShort()

class ContextSummonsInformation():
    def __init__(self):
        self.summons = []
        typev = reader.readType()
        if typev == "SpawnMonsterInformation;":
            self.entity = SpawnMonsterInformation()
        elif typev == "SpawnCharacterInformation;":
            self.entity = SpawnCharacterInformation()
        elif typev == "SpawnScaledMonsterInformation;":
            self.entity = SpawnScaledMonsterInformation()
        else:
            LOG.error(f"Unhandled type {typev} for ContextSummonsInformation/SpawnMonsterInformation")
        self.wave = reader.readByte()
        self.look = EntityLook()
        typev = reader.readType()
        print ("Typev", typev)
        self.entity.stats = FightCharacteristics()
        self.summons_len = reader.readUnsignedShort()
        for i in range(0, self.summons_len):
            typev = reader.readType()
            if typev == "GameContextBasicSpawnInformation;":
                if i == 0:
                    self.entity.spawn_info = ContextBasicSpawnInformations()
                if i > 0:
                    self.summons.append(ContextBasicSpawnInformations())
            else:
                LOG.error(f"Unhandled type {typev} for ContextSummonsInformation/GameContextBasicSpawnInformation")
        self.entity.contextual_id = self.entity.spawn_info.context_actor_info.contextual_id

class Summon():
    def __init__(self, val):
        self.entity = val
        self.contextual_id = val.contextual_id

def parse_fighter_summon():
    summon = []
    action_id = reader.readVarUhShort()
    source_id = reader.readDouble()
    summons_len = reader.readUnsignedShort()
    for _ in range(0, summons_len):
        typev = reader.readType()
        if typev == "GameFightCharacterInformations;":
            summon.append(Summon(FightCharacterInformations()))
        elif typev == "GameFightMonsterInformations;":
            summon.append(Summon(FightMonsterInformations()))
        elif typev == "GameFightTaxCollectorInformations;":
            summon.append(Summon(FightTaxCollectorInformations()))
        elif typev == "GameFightEntityInformation;":
            summon.append(Summon(FightEntityInformation()))
        elif typev == "GameFightMutantInformations;":
            summon.append(Summon(FightMutantInformation()))
        else:
            LOG.error(f"Unhandled type {typev} for parse_fighter_summon")
    return summon, source_id

def parse_summon():
    summon = []
    action_id = reader.readVarUhShort()
    source_id = reader.readDouble()
    summons_len = reader.readUnsignedShort()
    for i in range(0, summons_len):
        typev = reader.readType()
        if typev == "GameContextSummonsInformation;":
            summon.append(ContextSummonsInformation())
        else:
            LOG.error(f"No type available for {typev} for GameContextSummonsInformation")
    return summon, source_id
