import os, os.path, sys
from qt import SIGNAL, QDialog, QPushButton, QTextBrowser, QVBoxLayout, QSize, Qt

class GenHTML:
    def __init__ (self, reader, config, dump = False):
        self.reader = reader
        self.config = config
        self.module = ""
        self.toc    = "file:" + os.path.join (self.config ["PyKDEDocs"], "index.html")
        self.dump   = dump


    def homePage (self):
        moduleList = '<li><a href="%s">%s</a></li>\n'
        page = """<body text="#000000" bgcolor="#FFFFFF" link="#0000EE" vlink="#551A8B" alink="#FF0000">
&nbsp;
<table width="100%" >
<tr>
    <td valign=top>
        <table width="80%" >
        <tr bgcolor="#C8C8FF">
            <td><b>PyKDE API Reference - Modules</b></td>
        </tr>
        <tr bgcolor="#F0F0FF">
        <td><ul>
"""
        mods = self.reader.modules.keys ()
        mods.sort ()
        for mod in mods:
            if self.dump:
                page += moduleList % (os.path.join (mod, "index.html"), mod)
            else:
                page += moduleList % ("module:" + mod, mod)

        if self.dump:
            all = "allclasses.html"
        else:
            all = "allclasses:"

        page += """</ul>
        </td>
        </table>
    </td>
    <td valign=TOP>
        <center><h1>PyKDE API Reference</h1></center>
        <font size="+2">T</font>his section contains the PyKDE class reference for the
        current version of PyKDE.
        <ul>
            <li><a href="%s">Table of contents</a></li>
            <li>Modules</li>
            <li><a href=%s>All Classes</a><li>
        </ul>
    </td>
</tr></table>
</table>
</body>
""" % (self.toc, all)

        return page

    def classesPage (self, module):
        self.module = module

        if self.dump:
            home = os.path.join ("..", "index.html")
            all  = os.path.join ("..", "allclasses.html")
        else:
            home = "home:"
            all  = "allclasses:"

        page = """<table width="100%%"><tr>
            <td width ="70%%">
                <h1>%s Class Index</h1><hr>
            </td>
            <td  width="30%%" valign="top" align="right">
                <table>
                    <tr><td align="right"><a href="%s">Table of contents</a></td></tr>
                    <tr><td align="right"><a href="%s">Modules</a></td></tr>
                    <tr><td align="right"><a href="%s">All Classes</a></td></tr>
                </table>
            </td>
        </tr></table>
        """ % (self.module, self.toc, home, all)

        if self.module in self.reader.globals:
            if self.dump:
                globs = "%s-globals.html" % (self.module)
            else:
                globs = "globals:%s" % (self.module)
            page += '<a href = "%s">%s Global and Namespace members</a><p></p>\n' % (globs, self.module)

        columnStart  = '<td valign="top"><table border="0">\n'
        columnEnd    = '</table></td>'
        columnHead   = '<tr bgcolor="#fff0ff"><th>%s - %s</th></tr>\n'
        tableRow     = '<tr ><td><a href="class:%s">%s</a></td></tr>\n'
        dumpTableRow = '<tr ><td><a href="%s.html">%s</a></td></tr>\n'
        clsList      = self.reader.modules [self.module]
        clsList.sort ()
        nrows        = len (clsList)/3
        rows         = [nrows, nrows, nrows]
        remainder    = len (clsList)%3
        for i in range (remainder):
            rows [i] += 1

        page += '<table width="100%" border="0"><tr>\n' + columnStart

        offset = 0
        for i in rows:
            page += columnHead % (clsList [offset], clsList [offset + i - 1])
            for j in range (i):
                if not clsList [j + offset] in self.reader.namespaces and\
                    self.reader.elements [":".join ([self.module, clsList [j + offset]])].find ("abs") >= 0:
                    c = "<i>%s</i>" % clsList [j + offset]
                else:
                    c = clsList [j + offset]

                if self.dump:
                    page += dumpTableRow % (clsList [j + offset], c)
                else:
                    page += tableRow % (clsList [j + offset], c)
            page += columnEnd
            offset += i
            if offset < len (clsList):
                page += columnStart

        page += "</tr></table>"
        return page

    def allClassesPage (self):

        if self.dump:
            home = os.path.join ("..", "classref/index.html")        
            all  = os.path.join ("..", "allclasses.html")
        else:
            home = "home:"
            all  = "allclasses:"

        page = """<table width="100%%"><tr>
            <td width ="70%%">
                <h1>PyKDE Class Index</h1><hr>
            </td>
            <td  width="30%%" valign="top" align="right">
                <table>
                    <tr><td align="right"><a href="%s">Table of contents</a></td></tr>
                    <tr><td align="right"><a href="%s">Modules</a></td></tr>
                    <tr><td align="right"><a href="%s">All Classes</a></td></tr>
                </table>
            </td>
        </tr></table>
        """ % (self.toc, home, all)

        columnStart  = '<td valign="top"><table border="0">\n'
        columnEnd    = '</table></td>'
        columnHead   = '<tr bgcolor="#fff0ff"><th>%s - %s</th></tr>\n'
        tableRow     = '<tr ><td><a href="clsindex:%s">%s</A></td></tr>\n'
        dumpTableRow = '<tr ><td><a href="%s">%s</A></td></tr>\n'
        clsList      = []

        for mod in self.reader.modules:
            for cls in self.reader.modules [mod]:
                clsList.append (":".join ([cls.strip (), mod.strip ()]))

        clsList.sort ()

        nrows       = len (clsList)/3
        rows        = [nrows, nrows, nrows]
        remainder   = len (clsList)%3
        for i in range (remainder):
            rows [i] += 1

        page += '<table width="100%" border="0"><tr>\n' + columnStart

        offset = 0
        for i in rows:
            page += columnHead % (clsList [offset].split (":") [0], clsList [offset + i - 1].split (":") [0])
            for j in range (i):
                clsName, modName = clsList [j + offset].split (":")
                if not clsName in self.reader.namespaces and\
                    self.reader.elements [":".join ([modName, clsName])].find ("abs") >= 0:
                    c = "<i>%s</i>" % clsName
                else:
                    c = clsName

                if self.dump:
                    page += dumpTableRow % (os.path.join (modName, clsName + ".html"), c)
                else:
                    page += tableRow % ("+".join ([modName, clsName]), c)
            page += columnEnd
            offset += i
            if offset < len (clsList):
                page += columnStart

        page += "</tr></table>"
        return page

    def classPage (self, module, cls):
        KDERef = self.config ["KDERef"]
        self.module = module
        self.cls    = cls

        namespc = self.cls in self.reader.namespaces
        self.haveTxt = self.reader.readModuleText (self.module)

#        enumLine = '<li><b><a href="%s">%s</a></b> = {%s}'
        enumLine = '<li><b>%s</b> = {%s}'
        tdLine   = '<li>typedef %s %s</li>\n'
        clsLine  = '<li><b><a href="class:%s">%s</a></b>'

        if not namespc:
            baseClasses, abstract = self.reader.elements [":".join ([self.module, self.cls])].split (":")
        else:
            baseClasses = ""

        if self.dump:
            home    = os.path.join ("..", "index.html")
            all     = os.path.join ("..", "allclasses.html")
            modpage = "index.html"
        else:
            home    = "home:"
            all     = "allclasses:"
            modpage = "module:%s" % (self.module)

        page = """<table width="100%%"><tr>
            <td width ="70%%">
                <h1>class %s</h1><hr>
            </td>
            <td  width="30%%" valign="top" align="right">
                <table>
                    <tr><td align="right"><a href="%s">Table of contents</a></td></tr>
                    <tr><td align="right"><a href="%s">Modules</a></td></tr>
                    <tr><td align="right"><a href="%s">%s Classes</a></td></tr>
                    <tr><td align="right"><a href="%s">All Classes</a></td></tr>
                </table>
            </td>
        </tr></table>
        """ % (self.cls, self.toc, home, modpage, self.module, all)

        if self.dump:
            absref = os.path.join (self.config ["PyKDERef"], "glossary.html#abstract")
        else:
            absref = "popup:abstract"

        if not namespc and abstract.strip ():
#            if self.dump:
#                if self.config ["WebLink"]:
#                    clsLink = os.path.join (self.config ["KDERef"], self.module, "html", "class" + self.cls + ".html")
#                else:
#                    clsLink = os.path.join (self.config ["KDERef"], self.module, self.cls + ".html")
#                clsName = '<a href = "%s">%s </a><a href = "%s">(<i>abstract</i>)</a>' % (clsLink, self.cls, absref)
#            else:
            clsName = '%s <a href = "%s">(<i>abstract</i>)</a>' % (self.cls, absref)
        else:
#            if self.dump:
#                if self.config ["WebLink"]:
#                    clsLink = os.path.join (self.config ["KDERef"], self.module, "html", "class" + self.cls + ".html")
#                else:
#                    clsLink = os.path.join (self.config ["KDERef"], self.module, self.cls + ".html")
#                clsName = '<a href = "%s">%s </a>' % (clsLink, self.cls)
#            else:
            clsName = self.cls

        clsHdr = """<table>
        <tr><td width="10%%" align=left>Module</td>
            <td width="30%%" align=left>%s</td>
        </tr>
        <tr><td>Class</td>
            <td>%s</td>
        </tr>
        <tr><td>Inherits</td>
            <td>%s</td>
        </tr>
        </table>
        """  % (self.module, clsName, baseClasses)

        page += clsHdr

        elList = self.reader.classes [self.cls]
        elList.sort ()

        i    = 0
        imax = len (elList)

        if i < imax and elList [i].startswith ("class"):
            page += "<h3>classes</h3><ul>\n"
            while i < imax and elList [i].startswith ("class"):
                if namespc:
                    clsName = elList [i][7 + len (self.cls):]
                else:
                    clsName = elList [i][6:]
                page += clsLine % (elList [i][6:], clsName)
                i += 1

            page += "</ul>\n"

        if i < imax and elList [i].startswith ("enum"):
            page += "<h3>enums</h3><ul>\n"

            while i < imax and elList [i].startswith ("enum"):
                if namespc:
                    enumName = elList [i][6 + len (self.cls):]
                else:
                    enumName = self.undash (elList [i][5:])
                if self.dump and self.config ["WebLink"]:
                    linkName = os.path.join (KDERef, self.module, "html", "class" + self.cls.replace (".", "__") + ".html")
                else:
#                    linkName = os.path.join (KDERef, self.module, self.cls.replace (".", "__") + ".html#" + self.undot (enumName))
                    linkName = ""
                elements = ", ".join (self.reader.elements [":".join ([self.module, self.cls, elList [i]])])
#                page += enumLine % (linkName, enumName, elements)
                page += enumLine % (enumName, elements)
                i += 1

            page += "</ul>\n"

        if i < imax and elList [i].startswith ("etypedef"):
            page += "<h3>typedefs</h3><ul>\n"
            while i < imax and elList [i].startswith ("typedef"):
                page += tdLine % (elList [i][8:], "-")
                i += 1

            page += "</ul>\n"

        if i < imax and elList [i].startswith ("method"):
            page += '<h3>methods</h3><ul>\n'
            while i < imax and elList [i].startswith ("method"):
                page += self.formatMethod (elList [i][7:],\
                        "".join (self.reader.elements [":".join ([self.module, self.cls, elList [i]])]))
                i += 1

            page += "</ul>\n"

        if i < imax and elList [i].startswith ("operator"):
            page += "<h2>operators</h2><ul>\n"
            while i < imax and elList [i].startswith ("operator"):
                page += self.formatMethod (elList [i]. replace (":", "  "),\
                        "".join (self.reader.elements [":".join ([self.module, self.cls, elList [i]])]))
                i += 1

            page += "</ul>\n"

        if i < imax and elList [i].startswith ("variable"):
            page += '<h3>variables</h3><ul type = ""><li>\n'
            if self.dump:
                page += '<a href = "%s">variables</a>' % (os.path.join ("..", "glossary.html#variables"))
            else:
                page += '<a href = "popup:variables">variables</a>'
            page += '<table><tr  bgcolor="#fff0ff"><th>Variable</th><th>Type</th></tr>\n'
            tableLine = "<tr><td>%s</td><td>%s</td></tr>\n"
            while i < imax and elList [i].startswith ("variable"):
                t = self.reader.elements [":".join ([self.module, self.cls, elList [i]])] [0].strip ()
                page += tableLine % (elList [i][9:], t)
                i += 1

            page += "</table></li></ul>\n"

        return page

    def reversion (self, s):
        t = s.strip ()
        t = t.replace ("_", " ", 1)
        t = t.replace ("_", ".")
        return t

    def undash (self, s):
        dash = s.find ("-")
        if dash > 0:
            s = s [:dash]
        return s

    def undot (self, s):
        dot = s.find (".")
        while dot >= 0:
            s = s [dot + 1:]
            dot = s.find (".")
        return s

    def formatMethod (self, method, args):
        KDERef = self.config ["KDERef"]
        if self.dump:
            SLOT = '<a href="%s">SLOT</a> (Python callable)' % (os.path.join ("..", "glossary.html#slots"))
        else:
            SLOT = '<a href="popup:slots">SLOT</a> (Python callable)'
        text = ""
        method = self.undash (method)

        if self.cls:
#            if self.dump and self.config ["WebLink"]:
#                line = '<li><b><a href="%s" name="%s">%s</a></b> (' % (os.path.join (KDERef, self.module, "html",\
#                          "class" +  self.cls.replace (".", "__") + ".html"), method, method)
#            else:
#                line = '<li><b><a href="%s" name="%s">%s</a></b> (' % (os.path.join (KDERef, self.module,\
#                         self.cls.replace (".", "__") + ".html#" + method), method, method)
             line = '<li><b>%s</b> (' % (method)

        else:
 #           line = '<li><b><a href="%s">%s</a></b> (' % (os.path.join (KDERef, self.module, "all-globals.html#" + method), method)
           line = '<li><b>%s</b> (' % (method)

        returns = ""
        rList, tList, oList = args.split (":")

        oList = oList.split (",")
        notImpl = oList [0].strip () == "ig"

        if "|" in rList:
            rList = rList.split ("|")
            if rList [0] != "()":
                returns += rList [0].strip () + ", "
            for i in range (1, len (rList), 2):
                returns += rList [i].strip () + " " + rList [i + 1].strip ()
                if rList [i] != rList [-2]:
                    returns += ", "

        elif not rList:
            if self.cls and method == self.cls.split (".") [-1]:
                returns = "a %s instance" % method
            else:
                returns = "nothing"
        else:
            returns = rList.strip () #[1:-1]

        arglist = []

        if not tList:
            line += ""
        else:
            tList = tList.split ("|")
            for i in range (len (tList)):
                tList [i] = tList [i].replace (" bar ", " | ")

            for i in range (0, len (tList), 2):
                variable = tList [i].strip ()
                argtype  = tList [i + 1].strip () [1:-1]

                if argtype.find ("=") >= 0:
                    argtype, default = argtype.split ("=")
                    argtype = argtype.strip ()
                    default = default.strip ()
                else:
                    default = ""

                if argtype == "SIP_RXOBJ_CON":
                    variable = "slot"
                    argtype  = SLOT
                elif argtype == "SIP_SLOT_CON":
                    continue

                arglist.append ((variable, argtype, default))

                if default:
                    line += "%s = %s" % (variable, default)
                else:
                    line += variable

                if variable != tList [-2].strip ():
                    line += ", "

        line += ")"

        for case in oList:
            if case.find ("pure") >= 0:
                line += " = 0"

        line += '\n<table width = "100%"><tr><td width="50%" valign="top">'

        if notImpl:
            line += '<table><tr><td><i>Not Implemented</i></td></tr></table>\n'
            argtbl = ""
        else:
            line += '<table><tr><td>returns <i>%s</i></td></tr>\n' % returns

            if len (oList) > 1:
                for case in oList [1:]:
                    if case.find ("vers") >= 0:
                        vl, vh, sv = case [5:].split ("|")
                        vl = self.reversion (vl)
                        vh = self.reversion (vh)
                        sv = self.reversion (sv)

                        if vl and not vh:
                            line += '<tr><td>In versions %s and above only' % vl
                        elif vh and not vl:
                            line += '<tr><td>In versions <i>less than</i> %s only' % vh
                        elif vh and vl:
                            line += '<tr><td> In versions %s and above, but <i>less than </i> %s' % (vl, vh)

                        if sv:
                            line += '( %s only)' % sv

                        line += '</td></tr>\n'

                    if case.find ("stat") >= 0:
                        line += '<tr><td><i>static</i></td></tr>\n'

                    if case.find ("pure") >= 0:
                        if self.dump:
                            pure = os.path.join ("..", "glossary.html#purevirtual")
                        else:
                            pure = "popup:purevirtual"
                        line += '<tr><td><a href = "%s"><i>pure virtual</i></a></td></tr>\n' % (pure)

                    if case.find ("ren") >= 0:
                        line += "<tr><td>Renamed: was <i>'%s'</i> in C++</td></tr>\n"% case [4:]

            line += "</table>"


            if arglist:
                argtbl = '<table><tr  bgcolor="#fff0ff"><th>Argument</th><th>Type</th><th>Default</th></tr>\n'
                tableLine = "<tr><td>%s</td><td>%s</td><td>%s</td></tr>\n"

                for tpl in arglist:
                    argtbl += tableLine % (tpl [0], tpl [1], tpl [2])

                argtbl += "</table>\n"
            else:
                argtbl = ""

        key = ":".join ([self.module, self.cls, method])
        if key in self.reader.notes:
            text = '<tr><td bgcolor="#ffffc0">%s</td></tr>' % (self.reader.notes [key])
        else:
            text = ""

        if self.haveTxt and key in self.reader.moduleText:
            text += '<tr><td>%s</td></tr>' % (self.reader.moduleText [key])

        if not text:
            text = '<tr><td></td></tr>'

        line += argtbl + '</td><td width="50%%"><table>%s</table></td></tr></table>' % text

        line += "</li><hr>\n"
        return line


    def globalPage (self, module):
        KDERef = self.config ["KDERef"]
        self.module = module
        self.cls    = ""

        if self.dump:
            home    = os.path.join ("..", "index.html")
            all     = os.path.join ("..", "allclasses.html")
            modpage = "index.html"
        else:
            home    = "home:"
            all     = "allclasses:"
            modpage = "module:%s" % (self.module)

        self.haveTxt = self.reader.readModuleText (self.module)
        page = """<table width="100%%"><tr>
            <td width ="70%%">
                <h1>%s Globals</h1><hr>
            </td>
            <td  width="30%%" valign="top" align="right">
                <table>
                    <tr><td align="right"><a href="%s">Table of contents</a></td></tr>
                    <tr><td align="right"><a href="%s">Modules</a></td></tr>
                    <tr><td align="right"><a href="%s">%s Classes</a></td></tr>
                    <tr><td align="right"><a href="%s">All Classes</a></td></tr>
                </table>
            </td>
        </tr></table>
        """ % (self.module, self.toc, home, modpage, self.module, all)

        elList = self.reader.globals [self.module]
        elList.sort ()
        i = 0
        imax = len (elList)

        enumLine = '<li><b><a href="%s">%s</a></b> = {%s}'

        if i < imax and elList [i].startswith ("glenum"):
            page += "<h3>enums</h3><ul>\n"

            while i < imax and elList [i].startswith ("glenum"):
                enumName = self.undash (elList [i][7:])
                linkName = os.path.join (KDERef, self.module, "all-globals.html#" + self.undot (enumName))
                page += enumLine % (linkName, enumName, ", ".join (self.reader.elements [":".join ([self.module, elList [i]])]))
                i += 1

            page += "</ul>\n"

        if i < imax and elList [i].startswith ("global"):
            page += '<h3>global methods</h3><ul>\n'
            while i < imax and elList [i].startswith ("global"):
                page += self.formatMethod (elList [i][7:],\
                        "".join (self.reader.elements [":".join ([self.module, elList [i]])]))
                i += 1

            page += "</ul>\n"

        return page

class Popup (QDialog):
    def __init__ (self, text, parent, name = ""):
        QDialog.__init__ (self, parent, name)

        self.setCaption ("Info")

        popupLayout = QVBoxLayout(self,5,6)

        self.popupBrowser = QTextBrowser(self)
        self.popupBrowser.setSource (text)
        popupLayout.addWidget(self.popupBrowser)

        self.closeBtn = QPushButton("close", self)
        self.closeBtn.setMaximumSize(QSize(70,25))
        self.connect (self.closeBtn, SIGNAL ("clicked ()"), self.slotCloseClicked)
        popupLayout.addWidget(self.closeBtn)

        self.clearWState(Qt.WState_Polished)

    def slotCloseClicked (self):
        self.close (True)
