from functools import partial

from core.combat import addLevelUpStats, addStatsOnLevel, createCombatStats, handleSpawnerDeath
from core.component.spawner import MonsterNameRatio
from core.template import Template
from core.template.item import Axis

import siege.component
from siege.component import CombatTeam


class Combatant(Template):
    def __init__(self, name, **kwargs):
        Template.__init__(self, name, **kwargs)
        stats = kwargs.get('stats', {})
        if 'tuning' in kwargs:
            stats.update(kwargs['tuning'].STATS)
        self.add(createCombatStats(**stats))
        self.add(siege.component.Effects())
        self.combat.team = kwargs.get('team', CombatTeam.ZETA)
        self.combat.levels = kwargs.get('levels', [100] * 20)
        self.combat.experienceYield = kwargs.get('experienceYield', 0)
        if 'tuning' in kwargs:
            self.combat.onLevelUp = partial(addLevelUpStats, kwargs['tuning'])
        elif 'addStatsOnLevel' in kwargs:
            self.combat.onLevelUp = partial(addStatsOnLevel, kwargs['addStatsOnLevel'])


class Monster(Combatant):
    def __init__(self, name, weight=0, spawnOffset=None, biomes=[], **kwargs):
        self.name = name
        self.kwargs = kwargs
        self.actions = []
        Combatant.__init__(self, name, **kwargs)
        self.combat.onDamageSound = kwargs.get('onDamageSound', 'mods/core/audio/sfx/weapons/meleehit.ogg')
        self.add(siege.component.Monster())
        self.monster.weight = weight
        if biomes:
            self.monster.biomes = biomes
        if spawnOffset:
            self.monster.spawnOffset = spawnOffset

    def meleeAttack(self, **kwargs):
        self.attack = MonsterAttack(**kwargs)

        #self.actions.append(
        #    type(
        #        "{0}MeleeAttack".format(self.name),
        #        (MonsterMeleeAttack,),
        #        kwargs
        #    )
        #)

        return self.attack

    def customize(self, cls):
        """ Automatically wire up a monster-specific subclass. """
        self.monster.onCreate = cls.create
        if 'detectionArea' in self.kwargs:
            detectionArea = self.kwargs['detectionArea']
            self.kwargs.setdefault('dayDetectionArea', detectionArea)
            self.kwargs.setdefault('nightDetectionArea', detectionArea)

        for attr in ['loot', 'spawnTime', 'growlSound', 'dayDetectionArea', 'nightDetectionArea']:
            if attr in self.kwargs:
                setattr(cls, attr, self.kwargs[attr])

        return cls


class MonsterAttack(object):
    def __init__(self, **kwargs):
        self.kwargs = kwargs

    def customize(self, cls):
        for attr in ['hitFrames', 'power', 'detectionArea', 'cooldownTime', 'recoverTime', 'sound']:
            if attr in self.kwargs:
                setattr(cls, attr, self.kwargs[attr])
        return cls


class Spawner(Combatant):
    def __init__(self, name, **kwargs):
        Combatant.__init__(self, name, **kwargs)
        attrs = ['biomes', 'loot', 'monsters', 'spawnFrequency', 'spawnCapacity']
        self.spawner.set(attrs, kwargs)
        if 'monster' in kwargs:
            self.spawner.monsters.append(MonsterNameRatio(kwargs['monster']))
        self.placeable(floor_axis=Axis(animation='idle'), allowCollection=False)
        self.combat.onDeath = kwargs.get('onDeath', handleSpawnerDeath)
        self.combat.onDamageSound = kwargs.get('onDamageSound', 'mods/core/audio/sfx/monster/spawner_hit[1-3].ogg')
        self.combat.onDeathSound = kwargs.get('onDeathSound', 'mods/core/audio/sfx/monster/spawner_break.ogg')

    def placeable(self, **kwargs):
        if self.placement:
            del self.placement
        Template.placeable(self, **kwargs)
