import re

from ttfrog.db.base import StatsEnum
from ttfrog.db.schema.prototypes import BaseSpell

from .base import Parser

DAMAGE_DIE_PATTERN = re.compile(r"{@damage ([\dd]+)} (\w+) damage")


ONE_MILE_IN_FEET = 5280

SCHOOLS = {
    "A": "Abjuration",
    "C": "Conjuration",
    "D": "Divination",
    "E": "Enchantment",
    "V": "Evocation",
    "I": "Illusion",
    "N": "Necromancy",
    "T": "Transmutation",
}


class SpellParser(Parser):
    object_type = BaseSpell

    @property
    def target_range(self):
        if self.data["range"]["type"] == "special":
            return None
        elif self.data["range"]["distance"]["type"] in ["sight", "unlimited"]:
            return None
        elif self.data["range"]["distance"]["type"] in ["self", "touch"]:
            return 0
        elif self.data["range"]["distance"]["type"] == "feet":
            return self.data["range"]["distance"]["amount"]
        elif self.data["range"]["distance"]["type"] == "miles":
            return self.data["range"]["distance"]["amount"] * ONE_MILE_IN_FEET
        else:
            raise Exception(f"Don't know how to handle {self.data}")

    @property
    def target_shape(self):
        return self.data["range"]["type"]

    @property
    def target_size(self):
        return self.data["range"].get("amount", None)

    @property
    def duration(self):
        dur = self.data["duration"][0]
        if dur["type"] in ["instant", "permanent", "special"]:
            return dur["type"]
        elif dur["type"] == "timed":
            return f"{dur['duration']['amount']} {dur['duration']['type']}s"
        else:
            raise Exception(f"Don't know how to handle {dur}")

    @property
    def components(self):
        components = []
        if self.data["components"].get("v", False):
            components.append("verbal")

        if self.data["components"].get("s", False):
            components.append("somatic")

        mat = self.data["components"].get("m", False)
        if mat:
            desc = mat if type(mat) == str else mat["text"]
            components.append(f"materials: {desc}")
        return ", ".join(components)

    @property
    def school(self):
        return SCHOOLS[self.data["school"]]

    @property
    def saving_throw(self):
        return getattr(StatsEnum, self.data["savingThrow"][0]) if "savingThrow" in self.data else None

    @property
    def concentration(self):
        return self.data.get("duration", [])[0].get("concentration", False)

    @property
    def time(self):
        return f"{self.data['time'][0]['number']} {self.data['time'][0]['unit']}"

    @property
    def damage_die(self):
        m = DAMAGE_DIE_PATTERN.findall(self.description)
        return m[0][0] if m else None

    @property
    def damage_type(self):
        m = DAMAGE_DIE_PATTERN.findall(self.description)
        return m[0][1] if m else None
