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

"""implementation of charset models. The module provides the following
public attribute:

CHARSET_MODEL_FACTORIES = list containing all charset model factories
"""

import unicodedata

from PyQt4 import QtCore, QtGui
from chartables_model_factory import ModelFactoryBase, ModelBase, ModelColumn
from chartables_model_options import Options

CHARSET_MODEL_FACTORIES = []
#*******************************************************************
#
#*******************************************************************
class CT_HeaderCharsets(QtCore.QObject):
    """header for charset models"""

    def __init__(self, parent, cbChar, cbAbbr=None, cbName=None):
        QtCore.QObject.__init__(self, parent)
        
        self.columns = [
            ModelColumn(
                    title=self.trUtf8("Char"),
                    doc=self.trUtf8("Displays the char"),
                    flags=Options.CTF_NONE,
                    callback=cbChar,
                    ),
            ModelColumn(
                    title=self.trUtf8("Hex"),
                    doc=self.trUtf8("Displays the hexadecimal value of the char"),
                    flags=Options.CTF_SHOWCHARHEX,
                    callback=hex,
                    ),
            ModelColumn(
                    title=self.trUtf8("Int"),
                    doc=self.trUtf8("Displays the integer value of the char"),
                    flags=Options.CTF_SHOWCHARINT,
                    callback=int,
                    ),
            ]
        if cbAbbr:
            self.columns.append(
                ModelColumn(
                        title= self.trUtf8("Abbr."),
                        doc=self.trUtf8("Displays the abbreviated name of the char"),
                        flags=Options.CTF_SHOWCHARABBR,
                        callback=cbAbbr,
                    )
                )

        if cbName:
                self.columns.append(
                    ModelColumn(
                            title= self.trUtf8("Name"),
                            doc=self.trUtf8("Displays the name of the char"),
                            flags=Options.CTF_SHOWCHARNAME,
                            callback=cbName,
                        )
                    )
    
    
    
    def __getitem__(self, i):
        return self.columns[i]
    
    def __len__(self):
        return len(self.columns)

        

#*************************************************************************
# ASCII
#*************************************************************************
class _ControlChars(ModelBase):
    """Control chars implementation"""

    
    def __init__(self, parent, options=None):
        """
        constructor

        @param parent parent of the model
        @param options Options instance
        """
        self.char_names = (
                        "NUL",
                        "SOH",
                        "STX",
                        "ETX",
                        "EOT",
                        "ENQ",
                        "ACK",
                        "BEL",
                        "BS",
                        "HT",
                        "LF",
                        "VT",
                        "FF",
                        "CR",
                        "SO",
                        "SI",
                        "DLE",
                        "DC1",
                        "DC2",
                        "DC3",
                        "DC4",
                        "NAK",
                        "SYN",
                        "ETB",
                        "CAN",
                        "EM",
                        "SUB",
                        "ESC",
                        "FS",
                        "GS",
                        "RS",
                        "US",
                        )
        self.codec = QtCore.QTextCodec.codecForName("ISO 8859-1")
        header = CT_HeaderCharsets(
                            parent, 
                            QtCore.QChar, 
                            cbAbbr=self._toAbbr
                            )
        ModelBase.__init__(
                        self,
                        parent,
                        header=header,
                        rows = range(0x0, 0x20),
                        options=options,
                        )
    
    def _toAbbr(self, codepoint):
        """returns the name of a codepoint

        @param codepoint
        @return (string) name
        """
        return self.char_names[codepoint]



class _ASCIITable(ModelBase):
    """ASCII charset implementation"""

    def __init__(self, parent, options=None):
        """
        constructor

        @param parent parent of the model
        @param options Options instance
        """
        header = CT_HeaderCharsets(
                            parent, 
                            QtCore.QChar, 
                            cbAbbr=self._toAbbr,
                            cbName=self._toName
                            )
        ModelBase.__init__(self,
                        parent,
                        header=header,
                        rows=range(0x20, 0x80),
                        options=options,
                        )

    def _toName(self, codepoint):
        try:
            return unicodedata.name(unichr(codepoint), '').title()
        except: return ''
    
    def _toAbbr(self, codepoint):
        """returns the name of a codepoint

        @param codepoint
        @return (string) name
        """
        if codepoint == 0x7f:
            return "DEL"
        return ""

    

class CT_CharsetFactoryASCII(ModelFactoryBase):
    """ASCII charset model factory"""
    
    def trUtf8(self, what): return what
            
    def __init__(self, parent, options=None):
        ModelFactoryBase.__init__(self, parent, options=options)
        
        self._name = self.trUtf8("ASCII")
        self._models = (
            (_ControlChars, self.trUtf8("Control Chars")),
            (_ASCIITable, self.trUtf8("Basic Latin")),
            )

    def __len__(self):
        return len(self._models)

    def __getitem__(self, i):
        return self._models[i][0]
    
    def name(self):
        return self._name

    def displayName(self):
        return QtCore.QObject.trUtf8(self, self._name)
        
    def modelName(self, i):
        return self._models[i][1]

    def modelDisplayName(self, i):
        return QtCore.QObject.trUtf8(self, self._models[i][1])
    
    
        
CHARSET_MODEL_FACTORIES.append(CT_CharsetFactoryASCII)
#*******************************************************************
# ISO-8859
#*******************************************************************
class CT_CharsetFactoryISO8859(ModelFactoryBase):
    """ISO charset models factory"""

    def trUtf8(self, what): return what
    
    
    def __init__(self, parent, options=None):
        """constructor"""
        ModelFactoryBase.__init__(self, parent, options=options)
        
        self._name = "ISO-8859"
        self._models = (
        
            self.trUtf8("ISO 8859-1"),
            self.trUtf8("ISO 8859-2"),
            self.trUtf8("ISO 8859-3"),
            self.trUtf8("ISO 8859-4"),
            self.trUtf8("ISO 8859-5"),
            self.trUtf8("ISO 8859-6"),
            self.trUtf8("ISO 8859-7"),
            self.trUtf8("ISO 8859-8"),
            self.trUtf8("ISO 8859-9"),
            self.trUtf8("ISO 8859-10"),

            self.trUtf8("ISO 8859-13"),
            self.trUtf8("ISO 8859-14"),
            self.trUtf8("ISO 8859-15"),
            self.trUtf8("ISO 8859-16"),
            )
    
    def __len__(self):
        return len(self._models)

    def __getitem__(self, i):
        class ISOCharset(ModelBase):
            def __init__(self, parent, options=None):
                header = CT_HeaderCharsets(parent, self._toChar)
                ModelBase.__init__(self,
                                parent,
                                header= header,
                                rows=range(0x20, 0x7f) + range(0xa0, 0x100),
                                options=options,
                                )
            def _toChar(self, char):
                return self.codec.toUnicode(chr(char))
        
        ISOCharset.codec = QtCore.QTextCodec.codecForName(self._models[i])
        return ISOCharset
    
    
    def name(self):
        return self._name

    def displayName(self):
        return QtCore.QObject.trUtf8(self, self._name)
        
    def modelName(self, i):
        return self._models[i]

    def modelDisplayName(self, i):
        return QtCore.QObject.trUtf8(self, self._models[i])
        
    
CHARSET_MODEL_FACTORIES.append(CT_CharsetFactoryISO8859)    
#*******************************************************************
# KOI8
#*******************************************************************
class _KOI8_R(ModelBase):
    """KOI8-R charset implementation"""


    def __init__(self, parent, options=None):
        """
        constructor

        @param parent parent of the model
        @param options Options instance
        """
        self.codec = QtCore.QTextCodec.codecForName("KOI8-R")
        header = CT_HeaderCharsets(parent, self._toChar)
        ModelBase.__init__(self,
                        parent,
                        header=header,
                        rows=range(0x20, 0x100),
                        options=options,
                        )
        
    def _toChar(self, char):
        return self.codec.toUnicode(chr(char))


class _KOI8_U(ModelBase):
    """KOI8-U charset implementation"""

    
    def __init__(self, parent, options=None):
        """
        constructor

        @param parent parent of the model
        @param options Options instance
        """

        self.codec = QtCore.QTextCodec.codecForName("KOI8-U")
        header = CT_HeaderCharsets(parent, self._toChar)
        ModelBase.__init__(self,
                        parent,
                        header=header,
                        rows=range(0x20, 0x100),
                        options=options,
                        )

    def _toChar(self, char):
        return self.codec.toUnicode(chr(char))



class CT_CharsetFactoryKOI8(ModelFactoryBase):
    """KOI8 charset model factory"""

    def trUtf8(self, what): return what
            
    def __init__(self, parent, options=None):
        ModelFactoryBase.__init__(self, parent, options=options)
        
        self._name = self.trUtf8("KOI8")
        self._models = (
            (_KOI8_R, self.trUtf8("KOI8-R")),
            (_KOI8_U, self.trUtf8("KOI8-U")),
            )
        

    def __len__(self):
        return len(self._models)

    def __getitem__(self, i):
        return self._models[i][0]
    
    def name(self):
        return self._name

    def displayName(self):
        return QtCore.QObject.trUtf8(self, self._name)
        
    def modelName(self, i):
        return self._models[i][1]

    def modelDisplayName(self, i):
        return QtCore.QObject.trUtf8(self, self._models[i][1])
    
    
        
CHARSET_MODEL_FACTORIES.append(CT_CharsetFactoryKOI8)
#*******************************************************************
# TSCII
#*******************************************************************
class _TSCII(ModelBase):
    """TSCII charset implementation"""

    
    def __init__(self, parent, options=None):
        """
        constructor

        @param parent parent of the model
        @param options Options instance
        """
        self.codec = QtCore.QTextCodec.codecForName("TSCII")
        header = CT_HeaderCharsets(parent, self._toChar)
        ModelBase.__init__(self,
                        parent,
                        header=header,
                        rows=range(0x80, 0xFF),
                        options=options,
                        )
        
    def _toChar(self, char):
        return self.codec.toUnicode(chr(char))


class CT_CharsetFactoryTSCII(ModelFactoryBase):
    """TSCII charset model factory"""
    
    def trUtf8(self, what): return what
            
    def __init__(self, parent, options=None):
        ModelFactoryBase.__init__(self, parent, options=options)
        
        self._name = self.trUtf8("TSCII")
        self._models = (
            (_TSCII, self.trUtf8("TSCII")),
            )

    def __len__(self):
        return len(self._models)

    def __getitem__(self, i):
        return self._models[i][0]
    
    def name(self):
        return self._name

    def displayName(self):
        return QtCore.QObject.trUtf8(self, self._name)
        
    def modelName(self, i):
        return self._models[i][1]

    def modelDisplayName(self, i):
        return QtCore.QObject.trUtf8(self, self._models[i][1])


CHARSET_MODEL_FACTORIES.append(CT_CharsetFactoryTSCII)    

#*******************************************************************
# UTF-8
#
# More or less complete. Any fills welcome...
#
# for german see
#http://de.wikipedia.org/wiki/Liste_der_Unicode-Bl%C3%B6cke
#
#*******************************************************************
class CT_UTF_8Factory(ModelFactoryBase):
    """UTF-8 charset models factory"""

    def trUtf8(self, what): return what
        
            
    def __init__(self, parent, options=None):
        """constructor"""
        ModelFactoryBase.__init__(self, parent, options=options)
        
        self._name = self.trUtf8("UTF8")
        self._asciiFactory = CT_CharsetFactoryASCII(parent)    ###### parent
        self._models = (

                # taken over by CT_ASCIIFactory()
                #
                #((0x0, 0x20), self.trUtf8("ControlChars")),
                #((0x20, 0x80), self.trUtf8("Basic Latin")),
                
                ((0x80, 0x100), self.trUtf8("Latin-1 Supplement")),
                ((0x100, 0x180), self.trUtf8("Latin Extendet A")),
                ((0x180, 0x24f), self.trUtf8("Latin Extendet B")),
                ((0x250, 0x2af), self.trUtf8("IPA Extensions")),
                ((0x2b0, 0x2ff), self.trUtf8("Spacing Modifier Letters")),
                ((0x300, 0x36f), self.trUtf8("Combining Diacritical Marks")),
                ((0x370, 0x3ff), self.trUtf8("Greek and Coptic")),
                ((0x400, 0x4ff), self.trUtf8("Cyrillic")),
                ((0x500, 0x52f), self.trUtf8("Cyrillic Supplement")),
                ((0x530, 0x58f), self.trUtf8("Armenian")),
                ((0x590, 0x5ff), self.trUtf8("Hebrew")),
                ((0x600, 0x6ff), self.trUtf8("Arabic")),
                ((0x700, 0x74f), self.trUtf8("Syriac")),
                ((0x780, 0x7bf), self.trUtf8("Thaana")),
                ((0x900, 0x97f), self.trUtf8("Devanagari")),
                ((0x980, 0x9ff), self.trUtf8("Bengali")),
                ((0xa00, 0xa7f), self.trUtf8("Gurmukhi")),
                ((0xa80, 0xaff), self.trUtf8("Gujarati")),
                ((0xb00, 0xb7f), self.trUtf8("Oriya")),
                ((0xb80, 0xbff), self.trUtf8("Tamil")),
                ((0xc00, 0xc7f), self.trUtf8("Telugu")),
                ((0xc80, 0xcff), self.trUtf8("Kannada")),
                ((0xd00, 0xd7f), self.trUtf8("Malayalam")),
                ((0xd80, 0xdff), self.trUtf8("Sinhala")),
                ((0xe00, 0xe7f), self.trUtf8("Thai")),
                ((0xe80, 0xeff), self.trUtf8("Lao")),
                ((0xf00, 0xfff), self.trUtf8("Tibetan")),
                ((0x1000, 0x109f), self.trUtf8("Myanmar")),
                ((0x10a0, 0x10ff), self.trUtf8("Georgian")),
                ((0x1100, 0x11ff), self.trUtf8("Hangul Jamo")),
                ((0x1200, 0x137f), self.trUtf8("Ethiopic")),
                ((0x13a0, 0x13ff), self.trUtf8("Cherokee")),
                ((0x1400, 0x167f), self.trUtf8("Canadian Aboriginal Syllabics")),
                ((0x1680, 0x169f), self.trUtf8("Ogham")),
                ((0x16a0, 0x16ff), self.trUtf8("Runic")),
                ((0x1700, 0x171f), self.trUtf8("Tagalog")),
                ((0x1720, 0x173f), self.trUtf8("Hanunoo")),
                ((0x1740, 0x175f), self.trUtf8("Buhid")),
                ((0x1760, 0x177f), self.trUtf8("Tagbanwa")),
                ((0x1780, 0x17ff), self.trUtf8("Khmer")),
                ((0x1800, 0x18af), self.trUtf8("Mongolian")),
                ((0x1900, 0x194f), self.trUtf8("Limbu")),
                ((0x1950, 0x197f), self.trUtf8("Tai Le")),
                ((0x19e0, 0x19ff), self.trUtf8("Khmer Symbols")),
                ((0x1d00, 0x1d7f), self.trUtf8("Phonetic Extensions")),
                ((0x1e00, 0x1eff), self.trUtf8("Latin Extended Additional")),
                ((0x1f00, 0x1fff), self.trUtf8("Greek Extended")),
                ((0x2000, 0x206f), self.trUtf8("General Punctuation")),
                ((0x2070, 0x209f), self.trUtf8("Superscripts and Subscripts")),
                ((0x20a0, 0x20cf), self.trUtf8("Currency Symbols")),
                ((0x20d0, 0x20ff), self.trUtf8("Combining Diacritical Marks")),
                ((0x2100, 0x214f), self.trUtf8("Letterlike Symbols")),
                ((0x2150, 0x218f), self.trUtf8("Number Forms")),
                ((0x2190, 0x21ff), self.trUtf8("Arcolumns")),
                ((0x2200, 0x22ff), self.trUtf8("Mathematical Operators")),
                ((0x2300, 0x23ff), self.trUtf8("Miscelaneous Technical")),
                ((0x2400, 0x243f), self.trUtf8("Control Pictures")),
                ((0x2440, 0x245f), self.trUtf8("Optical Character Recognition")),
                ((0x2460, 0x24ff), self.trUtf8("Enclosed Alphanumerics")),
                ((0x2500, 0x257f), self.trUtf8("Box Drawing")),
                ((0x2580, 0x259f), self.trUtf8("Block Elements")),
                ((0x2600, 0x26ff), self.trUtf8("Miscelaneous Symbols")),
                ((0x2700, 0x27bf), self.trUtf8("Dingbats")),
                ((0x27c0, 0x27ef), self.trUtf8("Miscelaneous Mathematical Symbols-A")),
                ((0x27f0, 0x27ff), self.trUtf8("Supplement Arcolumns-A")),
                ((0x2800, 0x28ff), self.trUtf8("Braille Patterns")),
                ((0x2900, 0x297f), self.trUtf8("Supplement Arcolumns-B")),
                ((0x2980, 0x29ff), self.trUtf8("Miscelaneous Mathematical Symbols-B")),
                ((0x2a00, 0x2aff), self.trUtf8("Supplemental Mathematical Operators")),
                ((0x2b00, 0x2bff), self.trUtf8("Miscelaneous Symbols and Arcolumns")),
                ((0x2e80, 0x2eff), self.trUtf8("CJK Radicals Supplement")),
                ((0x2f00, 0x2fdf), self.trUtf8("KangXi Radicals")),
                ((0x2ff0, 0x2fff), self.trUtf8("Ideographic Description Chars")),
                ((0x3000, 0x303f), self.trUtf8("CJK Symbols and Punctuation")),
                ((0x3040, 0x309f), self.trUtf8("Hiragana")),
                ((0x30a0, 0x30ff), self.trUtf8("Katakana")),
                ((0x3100, 0x312f), self.trUtf8("Bopomofo")),
                ((0x3130, 0x318f), self.trUtf8("Hangul Compatibility Jamo")),
                ((0x3190, 0x319f), self.trUtf8("Kanbun")),
                ((0x31a0, 0x31bf), self.trUtf8("Bopomofo Extended")),
                ((0x31f0, 0x31ff), self.trUtf8("Katakana Phonetic Extensions")),
                ((0x3200, 0x32ff), self.trUtf8("Enclosed CJK Letters and Months")),
                ((0x3300, 0x33ff), self.trUtf8("CJK Compatibility")),
                ((0x3400, 0x4db5), self.trUtf8("CJK Unified Ideogr. Ext. A")),
                ((0x4dc0, 0x4dff), self.trUtf8("Yijing Hexagram Symbols")),
                ((0x4e00, 0x9fbb), self.trUtf8("CJK Unified Ideographs")),
                ((0xa000, 0xa48f), self.trUtf8("Yi Syllables")),
                ((0xa490, 0xa4cf), self.trUtf8("Yi Radicals")),
                ((0xac00, 0xd7a3), self.trUtf8("Hangul Syllables")),
                ((0xe000, 0xf8ff), self.trUtf8("Private Use Area")),
                ((0xf900, 0xfaff), self.trUtf8("CJK Compatibility Ideographs")),
                ((0xfb00, 0xfb4f), self.trUtf8("Alphabetic Presentation Forms")),
                ((0xfb50, 0xfdff), self.trUtf8("Arabic Presentation Forms-A")),
                ((0xfe00, 0xfe0f), self.trUtf8("Variation Selectors")),
                ((0xfe20, 0xfe2f), self.trUtf8("Combining Half Marks")),
                ((0xfe30, 0xfe4f), self.trUtf8("CJK Compatibility Forms")),
                ((0xfe50, 0xfe6f), self.trUtf8("Small Form Variants")),
                ((0xfe70, 0xfeff), self.trUtf8("Arabic Presentation Forms-B")),
                ((0xff00, 0xffef), self.trUtf8("Half- and Fullwidth Forms")),
                ((0xfff0, 0xffff), self.trUtf8("Specials")),
                ((0x10000, 0x1007f), self.trUtf8("Linear B Syllabary")),
                ((0x10080, 0x100ff), self.trUtf8("Linear B Ideograms")),
                ((0x10100, 0x1013f), self.trUtf8("Aegean Numbers")),
                ((0x10300, 0x1032f), self.trUtf8("Old Italic")),
                ((0x10330, 0x1034f), self.trUtf8("Gothic")),
                ((0x10380, 0x1039f), self.trUtf8("Ugaritic")),

                
                ((0x103a0, 0x103df), self.trUtf8("Old Persian")),
                

                ((0x10400, 0x1044f), self.trUtf8("Deseret")),
                ((0x10450, 0x1047f), self.trUtf8("Shavian")),
                ((0x10480, 0x104af), self.trUtf8("Osmanya")),
                ((0x10800, 0x1083f), self.trUtf8("Cypriot Syllabary")),

                ((0x10a00, 0x10a5f), self.trUtf8("Karoshthi")),

                ((0x1d000, 0x1d0ff), self.trUtf8("Byzantine Musical Symbols")),
                ((0x1d100, 0x1d1ff), self.trUtf8("Musical Symbols")),
                
                ((0x1d200, 0x1d24f), self.trUtf8("Ancient Greek Musical Notation")),
                
                
                ((0x1d300, 0x1d35f), self.trUtf8("Xuan Jing Symbols")),
                
                # left out some of the heavy knockers
                #
                #((0x1d400, 0x1d7ff), self.trUtf8("Mathematical Alphanumeric Symbols")),
                #((0x20000, 0x2a6d6), self.trUtf8("CJK Unified Ideographs Extension B")),
                #((0x2f800, 0x2fa1f), self.trUtf8("CJK Compatibility Ideographs Supplement")),
                
                ((0xe0000, 0xe007f), self.trUtf8("Tags")),
                ((0xe0100, 0xe01ef), self.trUtf8("Variation Selectors Supplement")),
                
                #((0xf0000, 0xffffd), self.trUtf8("Supplement Private Use Area-A")),
                #((0x100000, 0x10fffd), self.trUtf8("Supplement Private Use Area-B")),
                
                )


    def __len__(self):
        return len(self._models) +2

    def __getitem__(self, i):
        if i < 2:
            return self._asciiFactory[i]
        
        rng = self._models[i - 2][0]
        class Utf8CharRange(ModelBase):
            def __init__(self, parent, options=None):
                self.codec = QtCore.QTextCodec.codecForName("UTF-8")
                header = CT_HeaderCharsets(
                                    parent, 
                                    QtCore.QChar, 
                                    cbName=self._toName
                                    )
                ModelBase.__init__(self,
                                parent,
                                header=header,
                                rows=range(*rng),
                                options=options,
                                )
            def _toName(self, codepoint):
                try:
                    # looks like python provides names up to ~ 0xffff
                    return unicodedata.name(unichr(codepoint), '').title()
                except: return ''
        
        return Utf8CharRange
        
    
    def name(self):
        return self._name

    def displayName(self):
        return QtCore.QObject.trUtf8(self, self._name)
        
    def modelName(self, i):
        if i < 2:
            return self._asciiFactory.modelName(i)
        return self._models[i - 2][1]

    def modelDisplayName(self, i):
        if i < 2:
            return self._asciiFactory.modelDisplayName(i)
        return QtCore.QObject.trUtf8(self, self._models[i - 2][1])
    

CHARSET_MODEL_FACTORIES.append(CT_UTF_8Factory)
#*******************************************************************************
#
#*******************************************************************************

