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

class JsonError(Exception):
    pass

class Json:
    def __init__(self, color = None, bold = None, italic = None, underlined = None, obfuscated = None, translate = True):
        for e in [bold, italic, underlined, obfuscated, translate]:
            if not isinstance(e, (bool, type(None))):
                raise JsonError('{0} must be True, False o None'.format(e))
        if not isinstance(color, (str, type(None))):
            raise JsonError('color must be a str or None')

        self.color = color
        self.bold = bold
        self.italic = italic
        self.underlined = underlined
        self.obfuscated = obfuscated
        self.translate = translate

class JTxt(Json):

    def __init__(self, txt, color = 'dark_gray', bold = None, italic = False, underlined = None, obfuscated = None, translate = True):
        super().__init__(color, bold, italic, underlined, obfuscated, translate)

        if not isinstance(txt, str):
            raise JsonError('txt must be a str')
        self.txt = txt

    def json(self, format = 'item', translate = None):
        translate = translate if translate != None else self.translate
        if format == 'advancement':
            txt = self.txt.replace('\\\\u', '\\u')
        else:
            txt = self.txt.replace('\\n', '')
        json = '{'
        if translate:
            json += '"translate":"{0}"'.format(txt)
        else:
            json += '"text":"{0}"'.format(txt)
        json += ',"color":"{0}"'.format(self.color) if self.color!=None else ''
        json += ',"bold":{0}'.format(str(self.bold).lower()) if self.bold!=None else ''
        json += ',"italic":{0}'.format(str(self.italic).lower()) if self.italic!=None  else ''
        json += ',"underlined":{0}'.format(str(self.underlined).lower()) if self.underlined!=None  else ''
        json += ',"obfuscated":{0}'.format(str(self.obfuscated).lower()) if self.obfuscated!=None  else ''
        json += '}'
        return json

    def plain(self):
        return self.txt

    def plain_(self):
        t = '_'.join(self.txt.split(' '))
        for e in ["'", "\\", "(", ")"]:
            t = t.replace(e, "")
        return t.lower()

class JLine(Json):

    def __init__(self, line, color = 'dark_gray', bold = None, italic = False, underlined = None, obfuscated = None, translate = True):
        super().__init__(color, bold, italic, underlined, obfuscated, translate)

        self.line = []
        if isinstance(line, list):
            for i, e in enumerate(line):
                if isinstance(e, JTxt):
                    self.line.append(e)
                elif isinstance(e, str):
                    self.line.append(JTxt(e, color, bold, italic, underlined, obfuscated, translate))
                else:
                    raise JsonError("Must be a JTxt or str obj in [{0}] ({1})".format(i, e))
        else:
            raise JsonError("line must be a list of JTxt or str")

    def json(self, format = 'item', translate = None):
        txt = []
        for e in self.line:
            txt.append(e.json(format, translate))
        json = "["+','.join(txt)+"]"
        if format == 'item':
            return "'"+json+"'"
        return json

    def plain(self):
        txt = []
        for e in self.line:
            txt.append(e.plain())
        return ' '.join(txt)

    def plain_(self):
        txt = []
        for e in self.line:
            txt.append(e.plain_())
        return '_'.join(txt)

    def __getitem__(self, i):
        return self.line[i]

class JPar(Json):

    def __init__(self, par, color = 'dark_gray', bold = None, italic = False, underlined = None, obfuscated = None, translate = True):
        super().__init__(color, bold, italic, underlined, obfuscated)

        self.par = []
        if isinstance(par, list):
            for i, e in enumerate(par):
                if isinstance(e, JLine):
                    self.par.append(e)
                elif isinstance(e, JTxt):
                    self.par.append(JLine([e]))
                elif isinstance(e, str):
                    self.par.append(JLine([JTxt(e, color, bold, italic, underlined, obfuscated, translate)]))
                else:
                    raise JsonError("Must be a JLine, JTxt or str obj in [{0}]".format(i))
        else:
            raise JsonError("par must be a list of JLine, JTxt or str")

    def json(self, format = 'item', translate = None):
        txt = []
        for line in self.par:
            txt.append(line.json(format, translate))
        if format == 'advancement':
            txt.append(JLine(['\\n','\\n']).json(format, False))
        else:
            txt.append(JLine(['']).json(format, False))
        return ','.join(txt)

    def plain(self):
        txt = []
        for line in self.par:
            txt.append(line.plain())
        return ' '.join(txt)

    def plain_(self):
        txt = []
        for line in self.par:
            txt.append(line.plain_())
        return '_'.join(txt)

    def __getitem__(self, i):
        return self.par[i]

if __name__ == '__main__':
    a = JTxt('hola', obfuscated = True, bold = True)
    print([a.json()])
