# -*- coding: utf-8 -*-
"""
    htmlhelp2
    ~~~~~~~~~

    Build HTML help support files with [ALIAS] and [MAP] sections
    Note: Replaces original HTMLHelp builder!

    :copyright: Copyright 2012 David Motl
    :license: GNU GPL v.2
    
    $Id: html2.py,v 1.2 2016/02/24 18:26:03 dmotl Exp $
"""

import os
import codecs

from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.errors import ExtensionError
from sphinx.util import logging
from sphinx.util.console import bold, darkgreen  # type: ignore

class HTMLExtBuilder(StandaloneHTMLBuilder):
    name = 'html'
    
    encoding = 'iso8859_1'
        
    def init(self):
        StandaloneHTMLBuilder.init(self)
        
    def open_file(self, outdir, basename, mode='w'):
        # open a file with the correct encoding for the selected language
        return codecs.open(os.path.join(outdir, basename), mode,
            self.encoding, 'xmlcharrefreplace')
        
    def build_map(self, filename):
        """ Parse ctxhelp.h and make a dictionary which maps topics -> (num_id, label) """
        mmap = {}
        f = open(filename, "r")
        try:
           for line in f:
                x = line.split(None, 3)
                if len(x)==4 and x[0]=='#define' and x[2].isnumeric():
                    """ Get topic name """
                    start = x[3].find("/*");
                    if (start>=0):
                       end = x[3].find("*/", start+2);
                       if (end>=0):
                             topic = x[3][start+3:end].strip();
                             if len(topic)>0:
                                  mmap[topic] = (int(x[2]), x[1], None)
        finally:
           f.close()
        return mmap
        
    def dump_topics(self, outdir, topics):
        f = self.open_file(outdir, 'topics.ini', 'w')
        try:
            f.write('# C-Munipack 1.2 help topics\n')
            f.write('[MAP]\n')
            for topic in iter(topics):
                val = topics[topic]
                if val[1] and val[2]:
                    f.write(str(val[0]) + ' = ' + val[2] + '\n')
                else:
                    logger = logging.getLogger(__name__)
                    logger.warn("Missing topic: %s" % val[1])
        finally:
            f.close()
                    
    def get_outdated_docs(self):    
        if self.config.ctxhelp_file:
            mapfile = os.path.join(self.srcdir, self.config.ctxhelp_file)
            try:
                mapmtime = os.path.getmtime(mapfile)
            except Exception:
                raise ExtensionError('File not found: %s' % mapfile)
            for docname in self.env.found_docs:        
                targetname = self.get_outfilename(docname)
                try:
                    targetmtime = os.path.getmtime(targetname)
                except Exception:
                    targetmtime = 0                
                if mapmtime > targetmtime:
                    return self.env.found_docs
        return StandaloneHTMLBuilder.get_outdated_docs(self)
        
    def listdir(self, top):
        result = []
        for name in os.listdir(top):
            if isdir(os.path.join(top, name)):
                dirs.append(name)
            else:
                result.append(name)
        
    def make_makefile(self):
        logger = logging.getLogger(__name__)
        logger.info(bold('Creating Makefile.am...'), nonl=True)
    
        f = self.open_file(self.outdir, '../Makefile.am', 'w+')
        try:
            f.write("SUBDIRS = html")
        finally:
            f.close()

        f = self.open_file(self.outdir, 'Makefile.am', 'w+')
        try:
            basedir = self.outdir.replace('\\', '/')
            f.write("dochtmldir = $(datadir)/C-Munipack-2.0/doc/manual/en/html\n")
            f.write("nobase_dochtml_DATA = ")
            for (path, dirs, files) in os.walk(basedir):
                if path == basedir:
                    for name in files:
                        if name[0] != '.' and name.find("Makefile")!=0:
                            f.write(" \\\n\t" + name)
                else:
                    path = path.replace(basedir, '', 1)[1:]
                    path = path.replace('\\', '/')
                    for name in files:
                        if name[0] != '.' and name.find("Makefile")!=0:
                            f.write(" \\\n\t" + path + "/" + name)
            f.write("\n\n")
            f.write("EXTRA_DIST = $(nobase_dochtml_DATA)\n")
        finally:
            f.close()
            
        logger.info('done')            
        
    def make_topicmap(self):
        if self.config.ctxhelp_file:
            logger = logging.getLogger(__name__)
            logger.info(bold('dumping topic map...'), nonl=True)

            # Read map list of tuples (id, symbol, label)
            mmap = self.build_map(os.path.join(self.srcdir, self.config.ctxhelp_file))
            if mmap:
                # Resolve links
                for obj in self.env.domains['std'].get_objects():
                    label = obj[0]
                    if obj[2]=='label' and (label in mmap):
                        val = mmap[label]
                        mmap[label] = (val[0], val[1], obj[3] + self.out_suffix)
                # Update project file        
                self.dump_topics(self.outdir, mmap)
            else:
                logger.warn("No topics found in %s" % self.config.ctxhelp_file)
                
            logger.info('done')
        
    def handle_finish(self):
        StandaloneHTMLBuilder.handle_finish(self)
        self.make_topicmap()
        self.make_makefile()
            
def setup(app):
    # Replace original HTML Help builder
    app.add_builder(HTMLExtBuilder, override=True)
    app.add_config_value("ctxhelp_file", "include/ctxhelp.h", "env")


