#!/usr/bin/env python
# Copyright (C) 2013 Igalia S.L.
#
# 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 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, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301  USA

import os
import re
import sys

class WebKitDOMDocGenerator:

    DELETED_CLASSES = ["WebKitDOMBarInfo", "WebKitDOMHTMLPropertiesCollection", "WebKitDOMMemoryInfo", "WebKitDOMMicroDataItemValue", "WebKitDOMPropertyNodeList" ]

    def write_header(self):
        pass

    def write_section(self, symbol_file):
        raise NotImplementedError

    def write_deleted_classes(self):
        raise NotImplementedError

    def write_footer(self):
        pass

class WebKitDOMDocGeneratorDocs(WebKitDOMDocGenerator):

    def write_header(self):
        sys.stdout.write('''<?xml version="1.0"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
               "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
<!ENTITY version SYSTEM "version.xml">
]>
<book id="index" xmlns:xi="http://www.w3.org/2003/XInclude">
  <bookinfo>
    <title>WebKitDOMGTK+ Reference Manual</title>
    <releaseinfo>for WebKitDOMGTK+ &version;</releaseinfo>
  </bookinfo>

  <chapter>
    <title>Class Overview</title>
''')

    def write_section(self, symbol_file):
        basename = os.path.basename(symbol_file)
        sys.stdout.write('    <xi:include href="xml/%s"/>\n' % basename.replace(".symbols", ".xml"))

    def write_deleted_classes(self):
        for class_name in self.DELETED_CLASSES:
            sys.stdout.write('    <xi:include href="xml/%s.xml"/>\n' % class_name)

    def write_footer(self):
        sys.stdout.write('''  </chapter>

  <index id="index-all">
    <title>Index</title>
    <xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
  </index>
  <index id="api-index-deprecated" role="deprecated">
    <title>Index of deprecated symbols</title>
    <xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
  </index>

  <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
</book>
''')

class WebKitDOMDocGeneratorSections(WebKitDOMDocGenerator):

    def __init__(self, deprecated_symbol_file):
        self._first_decamelize_re = re.compile('(.)([A-Z][a-z]+)')
        self._second_decamelize_re = re.compile('([a-z0-9])([A-Z])')
        self._dom_class_re = re.compile('(^WebKitDOM)(.+)$')
        self._function_re = re.compile('^.+ (.+)\((.+)\)$')

        self._deprecated_symbols = self._deprecated_symbols(deprecated_symbol_file)

    def _dom_class(self, class_name):
        return self._dom_class_re.sub(r'\2', class_name)

    def _dom_class_decamelize(self, class_name):
        s1 = self._first_decamelize_re.sub(r'\1_\2', self._dom_class(class_name))
        retval = self._second_decamelize_re.sub(r'\1_\2', s1)

        # Fix some exceptions.
        retval = retval.replace('Web_Kit', 'WebKit')
        retval = retval.replace('X_Path', 'XPath')
        retval = retval.replace('HTMLI_Frame', 'HTML_IFrame')

        return retval

    def _deleted_class(self, function):
        for deleted_class in self.DELETED_CLASSES:
            decamelized = 'webkit_dom_%s' % self._dom_class_decamelize(deleted_class).lower()
            if function.startswith(decamelized):
                return deleted_class
        return None

    def _deprecated_symbols(self, symbol_file):
        retval = {}
        f = open(symbol_file, 'r')
        for line in f.readlines():
            match = self._function_re.match(line)
            if not match:
                continue

            function = match.group(1)
            args = match.group(2).split(', ')
            class_name = args[0].strip('*')
            if class_name == 'void':
                class_name = self._deleted_class(function)

            retval.setdefault(class_name, []).append(function)

        return retval

    def _symbol_list(self, symbol_file):
        retval = []
        f = open(symbol_file, 'r')
        for line in f.readlines():
            match = self._function_re.match(line)
            if not match or match.group(1).endswith('get_type'):
                continue
            retval.append(match.group(1))

        return retval

    def write_section(self, symbol_file):
        class_name = os.path.basename(symbol_file).replace(".symbols", "")
        is_custom = class_name == 'WebKitDOMCustom'
        is_interface = class_name == 'WebKitDOMEventTarget'
        is_object = class_name == 'WebKitDOMObject'
        sys.stdout.write('<SECTION>\n')
        sys.stdout.write('<FILE>%s</FILE>\n<TITLE>%s</TITLE>\n' % (class_name, class_name))
        if not is_custom:
            sys.stdout.write('%s\n' % class_name)
        sys.stdout.write('\n')
        sys.stdout.write('\n'.join(self._symbol_list(symbol_file)) + '\n')
        try:
            deprecated_functions = self._deprecated_symbols[class_name]
            sys.stdout.write('\n'.join(deprecated_functions) + '\n')
        except KeyError:
            pass
        if not is_custom:
            sys.stdout.write('\n<SUBSECTION Standard>\n')
            sys.stdout.write('%sClass\n' % class_name)
            dom_class = self._dom_class_decamelize(class_name).upper()
            sys.stdout.write('WEBKIT_TYPE_DOM_%s\n' % dom_class)
            sys.stdout.write('WEBKIT_DOM_%s\n' % dom_class)
            if is_object:
                sys.stdout.write('WEBKIT_IS_DOM_%s\n' % dom_class)
            else:
                sys.stdout.write('WEBKIT_DOM_IS_%s\n' % dom_class)
            sys.stdout.write('WEBKIT_DOM_%s_CLASS\n' % dom_class)
            if is_interface:
                sys.stdout.write('WEBKIT_DOM_%s_GET_IFACE\n' % dom_class)
            else:
                if is_object:
                    sys.stdout.write('WEBKIT_IS_DOM_%s_CLASS\n' % dom_class)
                else:
                    sys.stdout.write('WEBKIT_DOM_IS_%s_CLASS\n' % dom_class)
                sys.stdout.write('WEBKIT_DOM_%s_GET_CLASS\n' % dom_class)
            sys.stdout.write('\n<SUBSECTION Private>\n')
            if is_object:
                sys.stdout.write('%sPrivate\n' % class_name)
            sys.stdout.write('webkit_dom_%s_get_type\n' % dom_class.lower())
        sys.stdout.write('</SECTION>\n\n')

    def write_deleted_classes(self):
        for class_name in self.DELETED_CLASSES:
            sys.stdout.write('<SECTION>\n')
            sys.stdout.write('<FILE>%s</FILE>\n<TITLE>%s</TITLE>\n' % (class_name, class_name))
            sys.stdout.write('\n'.join([name for name in self._deprecated_symbols[class_name] if not name.endswith('get_type')]) + '\n')
            sys.stdout.write('\n<SUBSECTION Private>\n')
            sys.stdout.write('webkit_dom_%s_get_type\n' % self._dom_class_decamelize(class_name).lower())
            sys.stdout.write('</SECTION>\n\n')

    def write_footer(self):
        sys.stdout.write('<SECTION>\n')
        sys.stdout.write('<FILE>webkitdomdefines</FILE>\n<TITLE>WebKitDOMDefines</TITLE>\n')
        sys.stdout.write('<SUBSECTION Private>\n')
        sys.stdout.write('WEBKIT_API\nWEBKIT_DEPRECATED\nWEBKIT_DEPRECATED_FOR\n')
        sys.stdout.write('</SECTION>\n\n')


symbol_files = sys.stdin.read().strip('\n').split(' ')
if 'docs' in sys.argv[1:]:
    generator = WebKitDOMDocGeneratorDocs()
elif 'sections' in sys.argv[1:]:
    deprecated_symbol_file = None
    for symbol_file in symbol_files:
        if 'WebKitDOMDeprecated' in symbol_file:
            deprecated_symbol_file = symbol_file
            break
    generator = WebKitDOMDocGeneratorSections(deprecated_symbol_file)

generator.write_header()
for symbol_file in symbol_files:
    if 'WebKitDOMDeprecated' in symbol_file:
        continue
    generator.write_section(symbol_file)
generator.write_deleted_classes()
generator.write_footer()
