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

class JsonError(Exception):
    pass

class Json:
    def __init__(self, color = None, bold = None, italic = None, underlined = None, obfuscated = None):
        for e in [bold, italic, underlined, obfuscated]:
            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

class JTxt(Json):

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

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

    def json(self, name = False):
        json = '{'
        json += '"text":"{0}"'.format(self.txt) if not name else'"text":"{0}                                      "'.format(self.txt)
        json += ',"color":"{0}"'.format(self.color) if self.color!=None else ''
        if name:
            json += ',"bold":false'
        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 get(self):
        return JTxt(self.txt.replace('\\n', ''), self.color, self.bold, self.italic, self.underlined, self.obfuscated).json()

    def get_book(self, name = False):
        if name:
            return JTxt(self.txt.replace('\\\\u', '\\u'), self.color, False, self.italic, False, self.obfuscated).json()
        else:
            return JTxt(self.txt.replace('\\\\u', '\\u'), self.color, self.bold, self.italic, self.underlined, self.obfuscated).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):
        super().__init__(color, bold, italic, underlined, obfuscated)

        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, self.color, self.bold, self.italic, self.underlined, self.obfuscated))
                else:
                    raise JsonError("Must be a JTxt or str obj in [{0}]".format(i))
        else:
            raise JsonError("line must be a list of JTxt or str")

    def get(self):
        txt = []
        for e in self.line:
            if e.txt == '\\n':
                txt.append('{"text":""}')
            else:
                txt.append(e.get())
        return "'["+','.join(txt)+"]'"

    def get_book(self, name = False):
        txt = []
        for e in self.line:
            if e.txt == '\\n':
                txt.append('{"text":"\\n"}')
            else:
                txt.append(e.get_book(name))
        if name:
            txt.append('{"text":"                                           "}')
            return "["+','.join(txt)+"]"
        else:
            return ','.join(txt)

    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):
        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, self.color, self.bold, self.italic, self.underlined, self.obfuscated)]))
                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 get(self):
        txt = []
        for line in self.par:
            txt.append(line.get())
        return ','.join(txt)

    def get_book(self):
        txt = []
        for i,line in enumerate(self.par):
            txt.append(line.get_book())
        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.get()])
