from functions import *
from enum import Enum, auto
from random import randint
from scenes import entry


class Player:
    """Character Creation"""

    # Default Character
    def __init__(self, name, gender, age, race, job):
        # Personality
        self.name = name
        self.gender = gender
        self.age = age
        self.race = race
        self.job = job
        # Health
        self.currentHP = 100
        self.maxHP = 100
        # Levels
        self.level = 1
        self.exp = 0
        self.maxEXP = 100
        # Magic
        self.spells_known = []
        self.spells_ready = []
        # Equipment
        self.weapon = rock
        self.armor = tornRags
        # Defence
        self.ac = 0
        self.elemental_resistance = {DamageType.FIRE: False, DamageType.WATER: False, DamageType.LIGHTNING: False}
        self.physical_resistance = {DamageType.SLASHING: False, DamageType.CRUSHING: False, DamageType.PIERCING: False}
        # Ability Scores
        self.stats = {"Strength": 0,
                      "Dexterity": 0,
                      "Constitution": 0,
                      "Intelligence": 0,
                      "Wisdom": 0,
                      "Charisma": 0}
        # Ability Modifiers
        self.mods = {"Strength": 0,
                     "Dexterity": 0,
                     "Constitution": 0,
                     "Intelligence": 0,
                     "Wisdom": 0,
                     "Charisma": 0}
        # Held items
        self.inventory = {rock: {"Count": 1,
                                 "object": Weapon,
                                 "equipped": True
                                 },
                          tornRags: {"Count": 1,
                                     "object": Armor,
                                     "equipped": True
                                     },
                          GP1: {"Count": 10,
                                "object": Money,
                                "equipped": False
                                },
                          }

    # @property
    # def dexMod(self):
    #     return self.mods["Dexterity"]

    def getModifier(self):
        self.mods["Strength"] = -5 + self.stats["Strength"] // 2
        self.mods["Dexterity"] = -5 + self.stats["Dexterity"] // 2
        self.mods["Constitution"] = -5 + self.stats["Constitution"] // 2
        self.mods["Intelligence"] = -5 + self.stats["Intelligence"] // 2
        self.mods["Wisdom"] = -5 + self.stats["Wisdom"] // 2
        self.mods["Charisma"] = -5 + self.stats["Charisma"] // 2

    def set_stats(self):
        # Race
        if self.race == "elf":
            self.stats["Dexterity"] += 2
            self.stats["Intelligence"] += 2
        elif self.race == "human":
            self.stats["Strength"] += 2
            self.stats["Constitution"] += 2
        elif self.race == "dwarf":
            self.stats["Constitution"] += 2
            self.stats["Strength"] += 2

        # Job
        elif self.job == "warrior":
            self.stats["Strength"] += 2
            self.stats["Constitution"] += 1
        elif self.job == "ranger":
            self.stats["Dexterity"] += 2
            self.stats["Charisma"] += 1
        elif self.job == "mage":
            self.stats["Intelligence"] += 2
            self.stats["Charisma"] += 1

    def introduce(self):
        typingPrint("Adjusting for your race and class bonuses." + "\n", time)
        time.sleep(1)
        typingPrint(f'Welcome {self.name}, to Kanjin: An RPG Text Adventure.\n', time)

    def current_stats(self):
        """Prints a display of the user's current statistics."""
        print("Your current stats are:")
        print(f'Hit Points: {self.currentHP}/{self.maxHP}')
        print(f'Strength: {self.stats["Strength"]}')
        print(f'Dexterity: {self.stats["Dexterity"]}')
        print(f'Constitution: {self.stats["Constitution"]}')
        print(f'Intelligence: {self.stats["Intelligence"]}')
        print(f'Charisma: {self.stats["Charisma"]}')

    def current_equip(self):
        """Prints a list of items currently equipped."""
        typingPrint(f"You have equipped:\n {self.armor.name}\n"
                    f"    {self.armor.description}"
                    f"\n{self.weapon.name}\n"
                    f"    {self.weapon.description}\n", time)

    def new_char(self):
        """Outputs final stats, armour, and inventory"""
        typingPrint("We will now generate random stats for your character.\n", time)
        self.introduce()
        print(' ')
        time.sleep(2)
        self.rollStats()
        self.set_stats()
        print(' ')
        self.getModifier()
        self.current_stats()
        print(' ')
        time.sleep(2)
        self.current_equip()
        print(' ')
        current_inventory()
        print(' ')

    def rollStats(self):
        """Rolls stats 4d6kh3"""
        # Roll stats
        typingPrint("Rolling for Strength...\n", time)
        self.dice_rolls("Strength")
        typingPrint(f'Strength: {self.stats["Strength"]}\n', time)
        time.sleep(1)
        typingPrint("Rolling for Dexterity...\n", time)
        self.dice_rolls("Dexterity")
        typingPrint(f'Dexterity: {self.stats["Dexterity"]}\n', time)
        time.sleep(1)
        typingPrint("Rolling for Constitution...\n", time)
        self.dice_rolls("Constitution")
        typingPrint(f'Constitution: {self.stats["Constitution"]}\n', time)
        time.sleep(1)
        typingPrint("Rolling for Intelligence...\n", time)
        self.dice_rolls("Intelligence")
        typingPrint(f'Intelligence: {self.stats["Intelligence"]}\n', time)
        time.sleep(1)
        typingPrint("Rolling for Wisdom...\n", time)
        self.dice_rolls("Wisdom")
        typingPrint(f'Wisdom: {self.stats["Wisdom"]}\n', time)
        time.sleep(1)
        typingPrint("Rolling for Charisma...\n", time)
        self.dice_rolls("Charisma")
        typingPrint(f'Charisma: {self.stats["Charisma"]}\n', time)
        time.sleep(1)

    def health_check(self):
        """Print out current/max HP"""
        print(f'You have {self.currentHP}/{self.maxHP} HP.')

    def take_damage(self, DMGtype, size):
        """Define the damage type and dice size"""
        damage = randint(1, size)
        if DMGtype in self.elemental_resistance or DMGtype in self.physical_resistance:
            damage //= 2
        self.currentHP -= damage
        return damage

    def dice_rolls(self, attribute):
        """Rolling 4d6 to get stats for PC"""
        rolls = []
        # roll 4d6
        for roll in range(4):
            r = randint(1, 6)
            rolls.append(r)
        # Drop the lowest number
        del rolls[rolls.index(min(rolls))]
        self.stats[attribute] += sum(rolls)
        return attribute


# Inventory list
def current_inventory():
    """Prints a list of items in your backpack that aren't equipped to your person."""
    typingPrint(f'In your rucksack you have:\n', time)
    for item_key, item_value in user.inventory.items():
        for key, value in item_value.items():
            if key == "equipped" and value == False:
                typingPrint(f'{item_key.name}\n'
                            f'    {item_key.description}\n', time)


# Equipment list
def equipped():
    """Print currently equipped, print a list of held armor pieces,
    if input matches a held item, replace equipped condition"""

    print(f"You currently have equipped: {user.armor}\n")
    print("Would you like to equip something new? Y/N")
    answer = input(">> ").lower().strip()
    if answer == "n" or answer == "no":
        pass
    if answer == "y" or answer == "yes":
        answer = input(
            "Which which item from your inventory would you like to equip?" + "\n" + ">> ").lower().strip()
        for item_key, item_value in user.inventory.items():
            # item_info = dict
            for key, value in item_value.items():
                # Leather armor[items], "object"[key], Armor[value]
                if key == "object" and value == Armor:
                    print("\n", item_key)
    else:
        print("I'm sorry, I didn't understand that." + "\n" + "Would you like to equip something new? Y/N")


class DamageType(Enum):
    SLASHING = auto()
    CRUSHING = auto()
    PIERCING = auto()
    FIRE = auto()
    WATER = auto()
    LIGHTNING = auto()


class DamageMod(Enum):
    STRENGTH = auto()
    DEXTERITY = auto()
    CONSTITUTION = auto()
    INTELLIGENCE = auto()
    WISDOM = auto()
    CHARISMA = auto()


class Item:
    """The base class for all items"""

    def __init__(self, name, description, value, magical):
        self.name = name
        self.description = description
        self.value = value
        self.magical = magical

    def __repr__(self):
        return f"{self.name}\n=====\n{self.description}\nValue: {self.value}\n"


class Money(Item):
    """The currency item used in the world of Kanjin"""

    def __init__(self, name, amt, magical):
        self.name = name
        self.amt = amt
        self.magical = magical
        super().__init__(name=self.name,
                         description=f"A small round coin made of {self.name.lower()} "
                                     f"with the imperial city logo stamped on the face.",
                         value=self.amt,
                         magical=self.magical)


class Weapon(Item):
    """The base class for all weapons"""

    def __init__(self, name, description, value, damage1H, damage2H, dmgType, dmgMod, vers, thrown, magical):
        self.damage1H = damage1H
        self.damage2H = damage2H
        self.dmgType = dmgType
        self.dmgMod = dmgMod
        self.vers = vers
        self.thrown = thrown
        super().__init__(name, description, value, magical)

    def __repr__(self):
        return f"{self.name}\n=====\n{self.description}\nValue: {self.value}" \
               f"\nDamage: One Handed - {self.damage1H}" \
               f"\nDamage: Two Handed - {self.damage2H}\n" \
               f"Damage Type: {self.dmgType}\nMagical: {self.magical}.\n"


class Armor(Item):
    """The base class for all armor"""

    def __init__(self, name, description, value, grade, ac, disadvantage, dmgRes, magical):
        self.grade = grade
        self.ac = ac
        self.stealthDis = disadvantage
        self.dmgRes = dmgRes
        super().__init__(name, description, value, magical)

    def __repr__(self):
        if self.stealthDis:
            return f"{self.name}\n=====\n{self.description}\nValue: {self.value}\n" \
                   f"AC: {self.ac}\nMagical: {self.magical}"
        elif not self.stealthDis:
            return f"{self.name}\n=====\n{self.description}\nValue: {self.value}\n" \
                   f"AC: {self.ac}\nDisadvantage on Stealth checks: {self.stealthDis}\nMagical: {self.magical}"


# Different types of coins
GP1 = Money("Gold", 1, False)
SP1 = Money("Silver", 1, False)
CP1 = Money("Copper", 1, False)

rock = Weapon(
    name="Rock",
    description="A fist-sized rock, suitable for bludgeoning.",
    value="No value",
    damage1H=randint(1, 6),
    damage2H=0,
    dmgType=DamageType.CRUSHING,
    dmgMod=DamageMod.STRENGTH,
    vers=False,
    thrown=True,
    magical=False
)
tornRags = Armor(
    name="Torn Rags",
    description="A ripped and worn-out outfit.",
    value=0,
    grade="Light",
    ac=0,
    disadvantage=True,
    dmgRes="None",
    magical=False
)

# user = Player(*startGame())
user = Player("Jamie", "Male", 29, "Elf", "Mage")
# user.new_char()
entry()
