# -*- coding: utf-8 -*-

from nbt import *
from enum import Enum

class EnumPlus(Enum):
    def __new__(cls, value:int, string:str, color:str=None):
        member = object.__new__(cls)
        member._value_ = value
        member.string = string
        member.color = color
        return member
        
    def __int__(self):
        return self.value

    def __str__(self):
        return self.string

class Rank(EnumPlus):
    D = 0, 'd', 'red'
    C = 1, 'c', 'gold'
    B = 2, 'b', 'dark_purple'
    A = 3, 'a', 'dark_red'
    S = 4, 's', 'dark_green'

class WandElement(EnumPlus):
    Air = 1, 'air'
    Fire = 2, 'fire'
    Water = 3, 'water'
    Dark = 4, 'dark'
    Earth = 5, 'earth'
    Thunder = 6, 'thunder'

class WandUse(EnumPlus):
    Arch = 0, 'arch'
    Click_and_keep = 1, 'click_keep'
    Instant = 2, 'instant'

class ShardSize(EnumPlus):
    small = 0, 'small'
    medium = 1, 'medium'
    big = 2, 'big'

class ItemError(Exception):
    pass

class Item:

    count = 0

    def __init__(self, id:str='stone', name:JLine=None, lore:Lore=None, model:str=None, Itype:str='None', rank:Rank=None, stats:Stats=None, cost:int=0, element:WandElement=None, use:WandUse=None, custom_on:bool=False, custom_off:bool=False, holder:bool=True, set:str=None, other:str=None, bought:bool=False, price:int=0, give_tag:bool=False, book:bool=True, spell_text:str=None, model_3d=False):
        if not isinstance(name, JLine):
            name = JLine([name])
    # Minercaft item                      Default, Others
        self.id = id                    # Str ('stone')
    # Nbt
        self.Icount = Item.count        # Int
        self.name = name                # None, JLine
        self.lore = lore                # None, Lore
        self.model = model              # None, Str
        self.type = Itype               # Str ('None')
        self.rank = rank                # None, Rank
        self.stats = stats              # None, Stats
        self.cost = cost                # Int (0)               Spell casting cost
        self.element = element          # None, WandElement
        self.use = use                  # None, Str             [arch, instant, click_keep, other]
        self.other = other              # None, Str
        self.color = None               # None, Int             Leahter armor only
        self.armor_piece = None         # None, Str             [head, chest, legs, feet] Used only for armor
        self.model_3d = model_3d        # Bool
    # Flags
        self.custom_on = custom_on      # Bool (False)
        self.custom_off = custom_off    # Bool (False)
        self.holder = holder            # Bool (True)
        self.bought = bought            # Bool (False)
        give_tag = give_tag or (custom_on and custom_off)
        self.give_tag = give_tag        # Bool (False)
        self.book = book                # Bool (True)
    # Others
        self.set = set                  # None, Str             Scoreboard set name
        self.price = price              # Int (0)               Shop price
    # Add the rank, casting cost, and stats
        if spell_text != None:
            list = [JLine([ JTxt('spell', 'gray'), JTxt(': ', 'gray'), spell_text[0]] )] + spell_text[1:]
            self.lore.newpar(JPar(list))
        if self.rank != None:
            self.lore.newline(self.json_rank())
        if self.cost > 0:
            self.lore.newline(self.json_cost())
        if self.use != None:
            self.lore.newline(self.json_use())
        for stat in self.stats.lore():
            self.lore.newline(stat)

        Item.count += 1



# ======== CUSTOM METHODS ==============
    def name_plain_(self):
        if self.name != None:
            return self.name.plain_().split('.')[0]
        else:
            return str(self.Icount)

    def name_plain(self):
        if self.name != None:
            return self.name.plain().split('.')[0]
        else:
            return str(self.Icount)

    def json_rank(self):
        return JLine([JTxt('rank', 'gray'), ': ', JTxt(str(self.rank).upper(), self.rank.color)], 'gray')

    def json_cost(self):
        return JLine(['\\n', JTxt('cost', 'gray'), ': ', JTxt(str(self.cost), 'dark_aqua')], 'gray')

    def json_use(self):
        return JLine(['\\n', JTxt('use', 'gray'), ': ', JTxt(f'use.{self.use}', 'dark_gray')], 'gray')

    def data(self):
        name = self.name.json() if self.name != None else ''
        lore = self.lore.json() if self.lore != None else ''
        color = ',color:'+str(self.color) if self.color != None else ''
        display = ",display:{{Name:{},Lore:{}{}}}".format(name, lore, color)

        name_ = self.name_plain_() if self.name != None else 'None'
        model = ",CustomModelData:{0}".format(self.model) if self.model != None else ''
        other = ","+self.other if self.other != None else ''

        return f'{{Unbreakable:1b,Armory:1b,HideFlags:7,item_uuid:{self.Icount},name:{name_},type:{self.type},rank:{self.rank},cost:{self.cost},element:{self.element},use:{self.use},model_3d:{int(self.model_3d)},{self.stats.nbt()}{model}{display}{other},AttributeModifiers:[{{AttributeName:"generic.attack_speed",Name:"generic.attack_speed",Amount:0,Operation:0,UUID:[I;1,2,3,4],Slot:"mainhand"}}]}}'

    def get_anySlot_McStats(self):
        return self.stats.get_anySlot_McStats()
    def get_anySlot_CustomStats(self):
        return self.stats.get_anySlot_CustomStats()



# ======== SUBCLASSES ==============
class Wand(Item):

    def __init__(self, name, lore, rank, model = None, stats = Stats(), custom_on = False, custom_off = False, cost = 0, element = None, use = WandUse.Arch, holder = True, set = None, other = None, bought = False, price = 0, give_tag = False, book = True, spell_text = ['']):
        if model == None:
            model = str(1000 + int(element)*100 + int(rank))
            
        super().__init__('carrot_on_a_stick', name, lore, model, 'wand', rank, stats, cost, element, use, custom_on, custom_off, holder, set, other, bought, price, give_tag, book, spell_text, False)


class Passive(Item):

    def __init__(self, name, lore, rank, model = None, stats = Stats(), custom_on = False, custom_off = False, cost = 0, element = None, use = None, holder = True, set = None, other = None, bought = False, price = 0, give_tag = False, book = True):
        super().__init__('stick', name, lore, model, 'passive', rank, stats, cost, element, use, custom_on, custom_off, holder, set, other, bought, price, give_tag, book, None, False)

class Armor(Item):

    def __init__(self, id, name, lore, rank, model = None, stats = Stats(), custom_on = False, custom_off = False, cost = 0, element = None, use = None, holder = True, color = None, set = None, other = None, bought = False, price = 0, give_tag = False, book = True, model_3d=False):
        super().__init__(id, name, lore, model, 'armor', rank, stats, cost, element, use, custom_on, custom_off, holder, set, other, bought, price, give_tag, book, None, model_3d)

        if not isinstance(color, (int, type(None))):
            raise ItemError('Color must be a str int.')

        self.color = color
        if 'helmet' in id:
            self.armor_piece = 'head'
        elif 'chestplate' in id:
            self.armor_piece = 'chest'
        elif 'leggings' in id:
            self.armor_piece = 'legs'
        else:
            self.armor_piece = 'feet'

class Weapon(Item):

    def __init__(self, name, lore, rank, id = 'wooden_sword', model = None, stats = Stats(), custom_on = False, custom_off = False, cost = 0, element = None, use = None, holder = True, set = None, other = None, bought = False, price = 0, give_tag = False, book = True):
        super().__init__(id, name, lore, model, 'weapon', rank, stats, cost, element, use, custom_on, custom_off, holder, set, other, bought, price, give_tag, book, None, False)

class Shard(Item):

    def __init__(self, name, rank, size:ShardSize, lore = None, id = 'amethyst_shard', model = None, stats = Stats(), custom_on = False, custom_off = False, cost = 0, element = None, use = None, holder = False, set = None, other = None, bought = False, price = 0, give_tag = False, book = True):
        self.size = size
        other = f'size:"{size}"' if other == None else f'{other},size:"{size}"'
        if lore == None:
            lore = Lore([
                JPar([
                    JLine([ JTxt('enchant.fragile.name', 'gray', translate=True), 'enchant.fragile.l0'], 'dark_gray', italic=True, translate=True),
                    'enchant.fragile.l1'
                ], 'dark_gray', italic=True, translate=True)
            ])
        super().__init__(id, name, lore, model, 'shard', rank, stats, cost, element, use, custom_on, custom_off, holder, set, other, bought, price, give_tag, book, None, False)
