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

from nbt import *

def type_check(var, types, msg):
    if not isinstance(var, types):
        raise ItemError(msg)

class ItemError(Exception):
    pass

class Item:

    count = 0

    def __init__(self, id = 'stone', name = None, lore = None, model = None, Itype = 'None', rank = None, stats = None, cost = 0, element = None, use = None, custom_on = False, custom_off = False, holder = True, set = None, other = None, bought = False, price = 0, give_tag = False, book = True, spell_text = None):
        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, Str             [s, a, b, c, d] + shards for passives
        self.stats = stats              # None, Stats
        self.cost = cost                # Int (0)               Spell casting cost
        self.element = element          # None, Str             [air, fire, water, earth, dark, thunder]
        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
    # 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):
        list = {'s':'dark_green', 'a':'dark_red', 'b':'dark_purple', 'c':'gold', 'd':'red'}
        return JLine([JTxt('rank', 'gray'), ': ', JTxt(self.rank.upper(), list[self.rank])], '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('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 '{{Unbreakable:1b,Armory:1b,HideFlags:7,item_uuid:{},name:{},type:{},rank:{},cost:{},element:{},use:{},{}{}{}{},AttributeModifiers:[{{AttributeName:"generic.attack_speed",Name:"generic.attack_speed",Amount:0,Operation:0,UUID:[I;1,2,3,4],Slot:"mainhand"}}]}}'.format(self.Icount, name_, self.type, self.rank, self.cost, self.element, self.use, self.stats.nbt(), model, display, other)

    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 = "arch", holder = True, set = None, other = None, bought = False, price = 0, give_tag = False, book = True, spell_text = ['']):
        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)

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)

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):
        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)

        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)

class Shard(Item):

    def __init__(self, name, rank, 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):
        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)
