from dice import roll

from components import PaperDoll, Weapon, Attributes, Brain
from components.enums import Intention
from events.infos import MeleeAttackInfo
from systems.utilities import retract_intention, retract_turn


def run(scene):
    for brain in [b for b in scene.cm.get(Brain) if b.intention is Intention.MELEE_ATTACK]:
        entity = brain.entity
        target = brain.intention_target
        weapon = get_entity_weapon(scene, entity)
        attacker_attributes = scene.cm.get_one(Attributes, entity=entity)
        target_attributes = scene.cm.get_one(Attributes, entity=target)
        if weapon:
            attack = roll_attack(attacker_attributes, target_attributes, weapon)
            if attack.total_roll > 10:
                target_attributes.hp -= attack.damage
                # TODO convert this to a DealDamage event
                # TODO add an attack report message event
        else:
            scene.message("No weapon!")
        retract_intention(scene, entity)
        retract_turn(scene, entity)


def get_entity_weapon(scene, entity):
    paper_doll = scene.cm.get_one(PaperDoll, entity=entity)
    if paper_doll:
        weapon_id = paper_doll.weapon
        if weapon_id:
            return scene.cm.get_one(Weapon, entity=weapon_id)
    return None


def roll_attack(attacker_attributes, target_attributes, weapon) -> MeleeAttackInfo:
    strength = attacker_attributes.strength
    attack_roll = sum(roll('1d20')) + strength
    damage = sum(roll(weapon.damage))
    return MeleeAttackInfo(
        entity=attacker_attributes.entity,
        target=target_attributes.entity,
        total_roll=attack_roll,
        damage=damage
    )

