#!/usr/bin/env python

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import argparse
import os
import sys
from subprocess import Popen, PIPE, STDOUT
from BeautifulSoup import BeautifulSoup, Tag


DEFAULTS = dict(source              = '',
                author              = '',
                prefix              = '/usr/share',
                install_dir         = '',
                imports             = [],
                name                = '',
                keywords_content    = '',
                index_html          = '',
                devhelp_file        = '',
                compiler            = 'ldc2',
                d_files             = ()
               )

class Container(object):
    def __init__(self, **kwargs):
        for k,v in kwargs.items():
            setattr(self, k, v)


def basename(file_path, with_extension=False):
    if( file_path[-1] == os.sep ): file_path = file_path[0:-1]
    r = os.path.split(file_path)[1]
    return r if with_extension else r.rsplit('.', 1)[0]

def finder( directory = '/', extentions = [] ):
    file_list  = []
    for dirname, dirnames, filenames in os.walk(directory):
        for filename in filenames:
            f = os.path.join(dirname, filename)
            if os.path.splitext(f)[1] in extentions:
                file_list.append(f)
    return file_list


def main():
    c = Container(**DEFAULTS)

    parser = argparse.ArgumentParser()
    parser.add_argument('-a', '--author'    , action='store'  , help='Set author name'                              )
    parser.add_argument('-c', '--compiler'  , action='store'  , help='Set compiler, default: ldc2'                  )
    parser.add_argument('-p', '--prefix'    , action='store'  , help='Set prefix path for outputting devhelp book'  )
    parser.add_argument('-i', '--imports'   , action='append' , help='Set import dir'                               )
    parser.add_argument('-n', '--name'      , action='store'  , help='Set name name'                , required=True )
    parser.add_argument('-s', '--source'    , action='store'  , help='Set source dir to scan'       , required=True )


    parser.parse_args(namespace=c)

    # Use initialized var for set file and dir
    install_dir = os.path.normpath( os.path.join(c.prefix     , 'devhelp/books/', c.name ) )
    index_html  = os.path.normpath( os.path.join(install_dir  , 'index.html' ) )
    devhelp_file= os.path.normpath( os.path.join(install_dir  , c.name + '.devhelp2') )
    d_files     = finder(c.source, ['.d', '.di'])
    c.source    = os.path.normpath( c.source )

    if(not os.path.exists(install_dir)):
        os.makedirs(install_dir)

    keywords = []

    with open(index_html, 'w') as out_html, open(devhelp_file, 'w') as out_xml:
        # Add html header
        out_html.write('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "">\n')
        out_html.write('\t<html>\n')
        out_html.write('\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n\n')
        out_html.write('\t\t<title>'+ c.name +"</title>\n")
        out_html.write('\t</meta>\n')
        out_html.write('\t<body>\n')
        # Add xml header
        out_xml.write('<?xml version="1.0" encoding="utf-8" standalone="no"?>\n')
        out_xml.write('<!DOCTYPE book PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "">\n')
        out_xml.write('<book xmlns="http://www.devhelp.net/book" title="%s" link="index.html" author="%s" name="%s" version="2" language="d">\n' % (c.name, c.author, c.name))
        out_xml.write('\t<chapters>\n')
        # Create doc file from source and in same time complete index.html <name>.devhelp2 file
        for f in d_files:
            f = os.path.normpath( f )
            try:
                imports     = [ "-I%s" % i for i in c.imports if i != ""]
                arguments   = [c.compiler] + imports + ['-o-', '-d', '-c', f, '-Dd' + install_dir ]
                dc          = Popen( arguments, stdout=PIPE, stderr=STDOUT )
                outputlines = dc.stdout.readlines()
                dc.wait()
                for output in outputlines:
                    if output != "":
                        print output
            except Exception as e:
                print e
            base_dir            = basename( c.source )
            base_name           = basename( f ) # take file name without his path and without extention
            start               = len( c.source ) - len( base_dir )
            temp_name           = "_".join( f[start: f.find(base_name)].split(os.sep) ) + base_name +'.html'  # strip name
            generated_html_file = os.path.join( install_dir, base_name +'.html')
            html_file           = os.path.join( install_dir, temp_name  )
            if( os.path.exists( generated_html_file ) ):
                os.rename( generated_html_file, html_file )
                out_html.write('\t\t<a href="' + temp_name +'">' + temp_name + '</a><br>\n')
                out_xml.write('\t\t<sub name="'+ temp_name +'" link="'+ temp_name + '"/>\n')
                keywords +=  keyword_maker(html_file)
        # Add html footer
        out_html.write('\t</body>\n')
        out_html.write('</html>\n')
        # Add xml footer
        out_xml.write('\t</chapters>\n')
        out_xml.write('\t<functions>\n')

        for item in keywords:
            out_xml.write('\t\t<keyword type="%s" name="%s" link="%s"/>\n' % (item[0], item[1], item[2]))

        out_xml.write('\t</functions>\n')
        out_xml.write('</book>\n')


def keyword_maker(doc_html_file):
    keywords = []
    html_content = []
    with open( doc_html_file, 'r' ) as in_html:
        html_content = in_html.read()
    mySoup          = BeautifulSoup( html_content )
    dts             = mySoup.findAll( 'dt' )
    for dt in dts:
        type_name = ''
        decl_name = ''
        if(dt.big is not None):
            if(isinstance( dt.big.contents[0], Tag)):
                type_name = dt.big.contents[0].text
            else:
                type_name = dt.big.contents[0]
            if(dt.big.u is not None):
                decl_name =  dt.big.u.text
                link_html = basename(doc_html_file, True)
                keywords.append([type_name, decl_name, link_html])

    return keywords

if __name__ == '__main__':
    main()
