# -*- Mode: Python -*-

# GDBus - GLib D-Bus Library
#
# Copyright (C) 2008-2011 Red Hat, Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General
# Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
#
# Author: David Zeuthen <davidz@redhat.com>

import sys
import re
from os import path

from . import config
from . import utils
from . import dbustypes
from . import parser

# ----------------------------------------------------------------------------------------------------

class DocbookCodeGenerator:
    def __init__(self, ifaces):
        self.ifaces = ifaces
        self.generate_expand_dicts()

    def print_method_prototype(self, i, m, in_synopsis):
        max_method_len = 0
        if in_synopsis:
            for _m in i.methods:
                max_method_len = max(len(_m.name), max_method_len)
        else:
            max_method_len = max(len(m.name), max_method_len)

        max_signature_len = 0
        if in_synopsis:
            for _m in i.methods:
                for a in _m.in_args:
                    max_signature_len = max(len(a.signature), max_signature_len)
                for a in _m.out_args:
                    max_signature_len = max(len(a.signature), max_signature_len)
        else:
            for a in m.in_args:
                max_signature_len = max(len(a.signature), max_signature_len)
            for a in m.out_args:
                max_signature_len = max(len(a.signature), max_signature_len)

        if in_synopsis:
            self.out.write('<link linkend="gdbus-method-%s.%s">%s</link>%*s ('
                           %(utils.dots_to_hyphens(i.name), m.name, m.name, max_method_len - len(m.name), ''))
        else:
            self.out.write('%s%*s ('
                           %(m.name, max_method_len - len(m.name), ''))
        count = 0
        for a in m.in_args:
            if (count > 0):
                self.out.write(',\n%*s'%(max_method_len + 2, ''))
            self.out.write('IN  %s%*s %s'%(a.signature, max_signature_len - len(a.signature), '', a.name))
            count = count + 1
        for a in m.out_args:
            if (count > 0):
                self.out.write(',\n%*s'%(max_method_len + 2, ''))
            self.out.write('OUT %s%*s %s'%(a.signature, max_signature_len - len(a.signature), '', a.name))
            count = count + 1
        self.out.write(');\n')

    def print_signal_prototype(self, i, s, in_synopsis):
        max_signal_len = 0
        if in_synopsis:
            for _s in i.signals:
                max_signal_len = max(len(_s.name), max_signal_len)
        else:
            max_signal_len = max(len(s.name), max_signal_len)

        max_signature_len = 0
        if in_synopsis:
            for _s in i.signals:
                for a in _s.args:
                    max_signature_len = max(len(a.signature), max_signature_len)
        else:
            for a in s.args:
                max_signature_len = max(len(a.signature), max_signature_len)

        if in_synopsis:
            self.out.write('<link linkend="gdbus-signal-%s.%s">%s</link>%*s ('
                           %(utils.dots_to_hyphens(i.name), s.name, s.name, max_signal_len - len(s.name), ''))
        else:
            self.out.write('%s%*s ('
                           %(s.name, max_signal_len - len(s.name), ''))
        count = 0
        for a in s.args:
            if (count > 0):
                self.out.write(',\n%*s'%(max_signal_len + 2, ''))
            self.out.write('%s%*s %s'%(a.signature, max_signature_len - len(a.signature), '', a.name))
            count = count + 1
        self.out.write(');\n')

    def print_property_prototype(self, i, p, in_synopsis):
        max_property_len = 0
        if in_synopsis:
            for _p in i.properties:
                max_property_len = max(len(_p.name), max_property_len)
        else:
            max_property_len = max(len(p.name), max_property_len)

        max_signature_len = 0
        if in_synopsis:
            for _p in i.properties:
                max_signature_len = max(len(_p.signature), max_signature_len)
        else:
            max_signature_len = max(len(p.signature), max_signature_len)

        if in_synopsis:
            self.out.write('<link linkend="gdbus-property-%s.%s">%s</link>%*s'
                           %(utils.dots_to_hyphens(i.name), p.name, p.name, max_property_len - len(p.name), ''))
        else:
            self.out.write('%s%*s'
                           %(p.name, max_property_len - len(p.name), ''))
        if p.readable and p.writable:
            access = 'readwrite'
        elif p.readable:
            access = 'readable '
        else:
            access = 'writable '
        self.out.write('  %s  %s\n'%(access, p.signature))


    def print_synopsis_methods(self, i):
        self.out.write('  <refsynopsisdiv role="synopsis">\n'%())
        self.out.write('    <title role="synopsis.title">Methods</title>\n'%())
        self.out.write('    <synopsis>\n'%())
        for m in i.methods:
            self.print_method_prototype(i, m, in_synopsis=True)
        self.out.write('</synopsis>\n'%())
        self.out.write('  </refsynopsisdiv>\n'%())

    def print_synopsis_signals(self, i):
        self.out.write('  <refsect1 role="signal_proto">\n'%())
        self.out.write('    <title role="signal_proto.title">Signals</title>\n'%())
        self.out.write('    <synopsis>\n'%())
        for s in i.signals:
            self.print_signal_prototype(i, s, in_synopsis=True)
        self.out.write('</synopsis>\n'%())
        self.out.write('  </refsect1>\n'%())

    def print_synopsis_properties(self, i):
        self.out.write('  <refsect1 role="properties">\n'%())
        self.out.write('    <title role="properties.title">Properties</title>\n'%())
        self.out.write('    <synopsis>\n'%())
        for p in i.properties:
            self.print_property_prototype(i, p, in_synopsis=True)
        self.out.write('</synopsis>\n'%())
        self.out.write('  </refsect1>\n'%())

    def print_method(self, i, m):
        self.out.write('<refsect2 role="method" id="gdbus-method-%s.%s">\n'%(utils.dots_to_hyphens(i.name), m.name))
        self.out.write('  <title>The %s() method</title>\n'%(m.name))
        self.out.write('  <indexterm zone="gdbus-method-%s.%s"><primary sortas="%s.%s">%s.%s()</primary></indexterm>\n'%(utils.dots_to_hyphens(i.name), m.name, i.name_without_prefix, m.name, i.name, m.name))
        self.out.write('<programlisting>\n')
        self.print_method_prototype(i, m, in_synopsis=False)
        self.out.write('</programlisting>\n')
        self.out.write('%s\n'%(self.expand_paras(m.doc_string, True)))
        if m.in_args or m.out_args:
            self.out.write('<variablelist role="params">\n')
            for a in m.in_args:
                self.out.write('<varlistentry>\n'%())
                self.out.write('  <term><literal>IN %s <parameter>%s</parameter></literal>:</term>\n'%(a.signature, a.name))
                self.out.write('  <listitem>%s</listitem>\n'%(self.expand_paras(a.doc_string, True)))
                self.out.write('</varlistentry>\n'%())
            for a in m.out_args:
                self.out.write('<varlistentry>\n'%())
                self.out.write('  <term><literal>OUT %s <parameter>%s</parameter></literal>:</term>\n'%(a.signature, a.name))
                self.out.write('  <listitem>%s</listitem>\n'%(self.expand_paras(a.doc_string, True)))
                self.out.write('</varlistentry>\n'%())
            self.out.write('</variablelist>\n')
        if len(m.since) > 0:
            self.out.write('<para role="since">Since %s</para>\n'%(m.since))
        if m.deprecated:
            self.out.write('<warning><para>The %s() method is deprecated.</para></warning>'%(m.name))
        self.out.write('</refsect2>\n')

    def print_signal(self, i, s):
        self.out.write('<refsect2 role="signal" id="gdbus-signal-%s.%s">\n'%(utils.dots_to_hyphens(i.name), s.name))
        self.out.write('  <title>The "%s" signal</title>\n'%(s.name))
        self.out.write('  <indexterm zone="gdbus-signal-%s.%s"><primary sortas="%s::%s">%s::%s</primary></indexterm>\n'%(utils.dots_to_hyphens(i.name), s.name, i.name_without_prefix, s.name, i.name, s.name))
        self.out.write('<programlisting>\n')
        self.print_signal_prototype(i, s, in_synopsis=False)
        self.out.write('</programlisting>\n')
        self.out.write('%s\n'%(self.expand_paras(s.doc_string, True)))
        if s.args:
            self.out.write('<variablelist role="params">\n')
            for a in s.args:
                self.out.write('<varlistentry>\n'%())
                self.out.write('  <term><literal>%s <parameter>%s</parameter></literal>:</term>\n'%(a.signature, a.name))
                self.out.write('  <listitem>%s</listitem>\n'%(self.expand_paras(a.doc_string, True)))
                self.out.write('</varlistentry>\n'%())
            self.out.write('</variablelist>\n')
        if len(s.since) > 0:
            self.out.write('<para role="since">Since %s</para>\n'%(s.since))
        if s.deprecated:
            self.out.write('<warning><para>The "%s" signal is deprecated.</para></warning>'%(s.name))
        self.out.write('</refsect2>\n')

    def print_property(self, i, p):
        self.out.write('<refsect2 role="property" id="gdbus-property-%s.%s">\n'%(utils.dots_to_hyphens(i.name), p.name))
        self.out.write('  <title>The "%s" property</title>\n'%(p.name))
        self.out.write('  <indexterm zone="gdbus-property-%s.%s"><primary sortas="%s:%s">%s:%s</primary></indexterm>\n'%(utils.dots_to_hyphens(i.name), p.name, i.name_without_prefix, p.name, i.name, p.name))
        self.out.write('<programlisting>\n')
        self.print_property_prototype(i, p, in_synopsis=False)
        self.out.write('</programlisting>\n')
        self.out.write('%s\n'%(self.expand_paras(p.doc_string, True)))
        if len(p.since) > 0:
            self.out.write('<para role="since">Since %s</para>\n'%(p.since))
        if p.deprecated:
            self.out.write('<warning><para>The "%s" property is deprecated.</para></warning>'%(p.name))
        self.out.write('</refsect2>\n')

    def expand(self, s, expandParamsAndConstants):
        for key in self.expand_member_dict_keys:
            s = s.replace(key, self.expand_member_dict[key])
        for key in self.expand_iface_dict_keys:
            s = s.replace(key, self.expand_iface_dict[key])
        if expandParamsAndConstants:
            # replace @foo with <parameter>foo</parameter>
            s = re.sub('@[a-zA-Z0-9_]*', lambda m: '<parameter>' + m.group(0)[1:] + '</parameter>', s)
            # replace e.g. %TRUE with <constant>TRUE</constant>
            s = re.sub('%[a-zA-Z0-9_]*', lambda m: '<constant>' + m.group(0)[1:] + '</constant>', s)
        return s

    def expand_paras(self, s, expandParamsAndConstants):
        s = self.expand(s, expandParamsAndConstants).strip()
        if not s.startswith("<para"):
            s = "<para>%s</para>" % s
        return s

    def generate_expand_dicts(self):
        self.expand_member_dict = {}
        self.expand_iface_dict = {}
        for i in self.ifaces:
            key = '#%s'%(i.name)
            value = '<link linkend="gdbus-interface-%s.top_of_page">%s</link>'%(utils.dots_to_hyphens(i.name), i.name)
            self.expand_iface_dict[key] = value
            for m in i.methods:
                key = '%s.%s()'%(i.name, m.name)
                value = '<link linkend="gdbus-method-%s.%s">%s()</link>'%(utils.dots_to_hyphens(i.name), m.name, m.name)
                self.expand_member_dict[key] = value
            for s in i.signals:
                key = '#%s::%s'%(i.name, s.name)
                value = '<link linkend="gdbus-signal-%s.%s">"%s"</link>'%(utils.dots_to_hyphens(i.name), s.name, s.name)
                self.expand_member_dict[key] = value
            for p in i.properties:
                key = '#%s:%s'%(i.name, p.name)
                value = '<link linkend="gdbus-property-%s.%s">"%s"</link>'%(utils.dots_to_hyphens(i.name), p.name, p.name)
                self.expand_member_dict[key] = value
        # Make sure to expand the keys in reverse order so e.g. #org.foo.Iface:MediaCompat
        # is evaluated before #org.foo.Iface:Media ...
        self.expand_member_dict_keys = sorted(self.expand_member_dict.keys(), reverse=True)
        self.expand_iface_dict_keys = sorted(self.expand_iface_dict.keys(), reverse=True)

    def generate(self, docbook, outdir):
        for i in self.ifaces:
            self.out = open(path.join(outdir, '%s-%s.xml'%(docbook, i.name)), 'w')
            self.out.write(''%())
            self.out.write('<?xml version="1.0" encoding="utf-8"?>\n'%())
            self.out.write('<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"\n'%())
            self.out.write('               "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [\n'%())
            self.out.write(']>\n'%())
            self.out.write('<refentry id="gdbus-%s">\n'%(i.name))
            self.out.write('  <refmeta>'%())
            self.out.write('    <refentrytitle role="top_of_page" id="gdbus-interface-%s.top_of_page">%s</refentrytitle>\n'%(utils.dots_to_hyphens(i.name), i.name))
            self.out.write('  <indexterm zone="gdbus-interface-%s.top_of_page"><primary sortas="%s">%s</primary></indexterm>\n'%(utils.dots_to_hyphens(i.name), i.name_without_prefix, i.name))
            self.out.write('  </refmeta>'%())

            self.out.write('  <refnamediv>'%())
            self.out.write('    <refname>%s</refname>'%(i.name))
            self.out.write('    <refpurpose>%s</refpurpose>'%(i.doc_string_brief))
            self.out.write('  </refnamediv>'%())

            if len(i.methods) > 0:
                self.print_synopsis_methods(i)
            if len(i.signals) > 0:
                self.print_synopsis_signals(i)
            if len(i.properties) > 0:
                self.print_synopsis_properties(i)

            self.out.write('<refsect1 role="desc" id="gdbus-interface-%s">\n'%(utils.dots_to_hyphens(i.name)))
            self.out.write('  <title role="desc.title">Description</title>\n'%())
            self.out.write('  %s\n'%(self.expand_paras(i.doc_string, True)))
            if len(i.since) > 0:
                self.out.write('  <para role="since">Since %s</para>\n'%(i.since))
            if i.deprecated:
                self.out.write('<warning><para>The %s interface is deprecated.</para></warning>'%(i.name))
            self.out.write('</refsect1>\n'%())

            if len(i.methods) > 0:
                self.out.write('<refsect1 role="details" id="gdbus-methods-%s">\n'%(i.name))
                self.out.write('  <title role="details.title">Method Details</title>\n'%())
                for m in i.methods:
                    self.print_method(i, m)
                self.out.write('</refsect1>\n'%())

            if len(i.signals) > 0:
                self.out.write('<refsect1 role="details" id="gdbus-signals-%s">\n'%(i.name))
                self.out.write('  <title role="details.title">Signal Details</title>\n'%())
                for s in i.signals:
                    self.print_signal(i, s)
                self.out.write('</refsect1>\n'%())

            if len(i.properties) > 0:
                self.out.write('<refsect1 role="details" id="gdbus-properties-%s">\n'%(i.name))
                self.out.write('  <title role="details.title">Property Details</title>\n'%())
                for s in i.properties:
                    self.print_property(i, s)
                self.out.write('</refsect1>\n'%())

            self.out.write('</refentry>\n')
            self.out.write('\n')

