import re
from sphinx.util.compat import Directive
from docutils import nodes

class DialectDirective(Directive):
    has_content = True

    _dialects = {}

    def _parse_content(self):
        d = {}
        d['default'] = self.content[0]
        d['text'] = []
        idx = 0
        for line in self.content[1:]:
            idx += 1
            m = re.match(r'\:(.+?)\: +(.+)', line)
            if m:
                attrname, value = m.group(1, 2)
                d[attrname] = value
            else:
                break
        d["text"] = self.content[idx + 1:]
        return d

    def _dbapi_node(self):

        dialect_name, dbapi_name = self.dialect_name.split("+")

        try:
            dialect_directive = self._dialects[dialect_name]
        except KeyError:
            raise Exception("No .. dialect:: %s directive has been established"
                                    % dialect_name)

        output = []

        content = self._parse_content()

        parent_section_ref = self.state.parent.children[0]['ids'][0]
        self._append_dbapi_bullet(dialect_name, dbapi_name,
                                        content['name'], parent_section_ref)

        p = nodes.paragraph('', '',
                    nodes.Text(
                        "Support for the %s database via the %s driver." % (
                                dialect_directive.database_name,
                                content['name']
                        ),
                        "Support for the %s database via the %s driver." % (
                                dialect_directive.database_name,
                                content['name']
                        )
                    ),
        )

        self.state.nested_parse(content['text'], 0, p)
        output.append(p)

        if "url" in content or "driverurl" in content:
            sec = nodes.section(
                    '',
                    nodes.title("DBAPI", "DBAPI"),
                    ids=["dialect-%s-%s-url" % (dialect_name, dbapi_name)]
            )
            if "url" in content:
                text = "Documentation and download information (if applicable) "\
                        "for %s is available at:\n" % content["name"]
                uri = content['url']
                sec.append(
                    nodes.paragraph('', '',
                        nodes.Text(text, text),
                        nodes.reference('', '',
                            nodes.Text(uri, uri),
                            refuri=uri,
                        )
                    )
                )
            if "driverurl" in content:
                text = "Drivers for this database are available at:\n"
                sec.append(
                    nodes.paragraph('', '',
                        nodes.Text(text, text),
                        nodes.reference('', '',
                            nodes.Text(content['driverurl'], content['driverurl']),
                            refuri=content['driverurl']
                        )
                    )
                )
            output.append(sec)


        if "connectstring" in content:
            sec = nodes.section(
                    '',
                    nodes.title("Connecting", "Connecting"),
                    nodes.paragraph('', '',
                        nodes.Text("Connect String:", "Connect String:"),
                        nodes.literal_block(content['connectstring'],
                            content['connectstring'])
                    ),
                    ids=["dialect-%s-%s-connect" % (dialect_name, dbapi_name)]
            )
            output.append(sec)

        return output

    def _dialect_node(self):
        self._dialects[self.dialect_name] = self

        content = self._parse_content()
        self.database_name = content['name']

        self.bullets = nodes.bullet_list()
        text = "The following dialect/DBAPI options are available.  "\
                "Please refer to individual DBAPI sections for connect information."
        sec = nodes.section('',
                nodes.paragraph('', '',
                    nodes.Text(
                        "Support for the %s database." % content['name'],
                        "Support for the %s database." % content['name']
                    ),
                ),
                nodes.title("DBAPI Support", "DBAPI Support"),
                nodes.paragraph('', '',
                    nodes.Text(text, text),
                    self.bullets
                ),
                ids=["dialect-%s" % self.dialect_name]
            )

        return [sec]

    def _append_dbapi_bullet(self, dialect_name, dbapi_name, name, idname):
        env = self.state.document.settings.env
        dialect_directive = self._dialects[dialect_name]

        list_node = nodes.list_item('',
                nodes.paragraph('', '',
                    nodes.reference('', '',
                                nodes.Text(name, name),
                                refdocname=self.docname,
                                refuri=env.app.builder.get_relative_uri(
                                        dialect_directive.docname, self.docname) +
                                            "#" + idname
                            ),
                    #nodes.Text(" ", " "),
                    #nodes.reference('', '',
                    #            nodes.Text("(connectstring)", "(connectstring)"),
                    #            refdocname=self.docname,
                    #            refuri=env.app.builder.get_relative_uri(
                    #                    dialect_directive.docname, self.docname) +
                    ##                        "#" + ("dialect-%s-%s-connect" %
                    #                                (dialect_name, dbapi_name))
                    #        )
                    )
            )
        dialect_directive.bullets.append(list_node)

    def run(self):
        env = self.state.document.settings.env
        self.docname = env.docname

        self.dialect_name = dialect_name = self.content[0]

        has_dbapi = "+" in dialect_name
        if has_dbapi:
            return self._dbapi_node()
        else:
            return self._dialect_node()

def setup(app):
    app.add_directive('dialect', DialectDirective)

