/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/




#include "HelpCompiler.hxx"
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <libxslt/xslt.h>
#include <libxslt/xsltInternals.h>
#include <libxslt/transform.h>
#include <libxslt/xsltutils.h>
#ifdef __MINGW32__
#include <tools/prewin.h>
#include <tools/postwin.h>
#endif
#include <osl/thread.hxx>

static void impl_sleep( sal_uInt32 nSec )
{
    TimeValue aTime;
    aTime.Seconds = nSec;
    aTime.Nanosec = 0;

    osl::Thread::wait( aTime );
}

HelpCompiler::HelpCompiler(StreamTable &in_streamTable, const fs::path &in_inputFile, 
    const fs::path &in_src, const fs::path &in_resEmbStylesheet, 
    const std::string &in_module, const std::string &in_lang, bool in_bExtensionMode)
    : streamTable(in_streamTable), inputFile(in_inputFile),
    src(in_src), module(in_module), lang(in_lang), resEmbStylesheet(in_resEmbStylesheet),
	bExtensionMode( in_bExtensionMode )
{
    xmlKeepBlanksDefaultValue = 0;
}

xmlDocPtr HelpCompiler::getSourceDocument(const fs::path &filePath) 
{
    static const char *params[4 + 1];
    static xsltStylesheetPtr cur = NULL;

	xmlDocPtr res;
	if( bExtensionMode )
	{
		res = xmlParseFile(filePath.native_file_string().c_str());
        if( !res ){
            impl_sleep( 3 );
            res = xmlParseFile(filePath.native_file_string().c_str());
        }
	}
	else
	{
		if (!cur)
		{
			static std::string fsroot('\'' + src.toUTF8() + '\'');
			static std::string esclang('\'' + lang + '\'');
	        
			xmlSubstituteEntitiesDefault(1);
			xmlLoadExtDtdDefaultValue = 1;
			cur = xsltParseStylesheetFile((const xmlChar *)resEmbStylesheet.native_file_string().c_str());

			int nbparams = 0;
			params[nbparams++] = "Language";
			params[nbparams++] = esclang.c_str();
			params[nbparams++] = "fsroot";
			params[nbparams++] = fsroot.c_str();
			params[nbparams] = NULL;
		}
		xmlDocPtr doc = xmlParseFile(filePath.native_file_string().c_str());
		if( !doc )
        {
            impl_sleep( 3 );
            doc = xmlParseFile(filePath.native_file_string().c_str());
        }

		//???res = xmlParseFile(filePath.native_file_string().c_str());

        res = xsltApplyStylesheet(cur, doc, params);
		xmlFreeDoc(doc);
	}
    return res;
}

HashSet HelpCompiler::switchFind(xmlDocPtr doc)
{
    HashSet hs;
    xmlChar *xpath = (xmlChar*)"//switchinline";

    xmlXPathContextPtr context = xmlXPathNewContext(doc);
    xmlXPathObjectPtr result = xmlXPathEvalExpression(xpath, context);
    xmlXPathFreeContext(context);
    if (result)
    {
        xmlNodeSetPtr nodeset = result->nodesetval;
        for (int i = 0; i < nodeset->nodeNr; i++)
        {
            xmlNodePtr el = nodeset->nodeTab[i];
            xmlChar *select = xmlGetProp(el, (xmlChar*)"select");
            if (select)
            {
                if (!strcmp((const char*)select, "appl"))
                {
                    xmlNodePtr n1 = el->xmlChildrenNode;
                    while (n1)
                    {
                        if ((!xmlStrcmp(n1->name, (const xmlChar*)"caseinline")))
                        {
                            xmlChar *appl = xmlGetProp(n1, (xmlChar*)"select");
                            hs.push_back(std::string((const char*)appl));
                            xmlFree(appl);
                        }
                        else if ((!xmlStrcmp(n1->name, (const xmlChar*)"defaultinline")))
                            hs.push_back(std::string("DEFAULT"));
                        n1 = n1->next;
                    }
                }
                xmlFree(select);
            }
        }
        xmlXPathFreeObject(result);
    }
    hs.push_back(std::string("DEFAULT"));
    return hs;
}

// returns a node representing the whole stuff compiled for the current
// application.
xmlNodePtr HelpCompiler::clone(xmlNodePtr node, const std::string& appl)
{
    xmlNodePtr parent = xmlCopyNode(node, 2);
    xmlNodePtr n = node->xmlChildrenNode;
    while (n != NULL)
    {
        bool isappl = false;
        if ( (!strcmp((const char*)n->name, "switchinline")) || 
             (!strcmp((const char*)n->name, "switch")) )
        {
            xmlChar *select = xmlGetProp(n, (xmlChar*)"select");
            if (select)
            {
                if (!strcmp((const char*)select, "appl"))
                    isappl = true;
                xmlFree(select);
            }
        }
        if (isappl)
        {
            xmlNodePtr caseNode = n->xmlChildrenNode;
            if (appl == "DEFAULT") 
            {
                while (caseNode)
                {
                    if (!strcmp((const char*)caseNode->name, "defaultinline"))
                    {
                        xmlNodePtr cnl = caseNode->xmlChildrenNode;
                        while (cnl)
                        {
                            xmlAddChild(parent, clone(cnl, appl));
                            cnl = cnl->next;
                        }
                        break;
                    }
                    caseNode = caseNode->next;
                }
            }
            else
            {
                while (caseNode)
                {
                    isappl=false;
                    if (!strcmp((const char*)caseNode->name, "caseinline"))
                    {
                        xmlChar *select = xmlGetProp(n, (xmlChar*)"select");
                        if (select)
                        {
                            if (!strcmp((const char*)select, appl.c_str()))
                                isappl = true;
                            xmlFree(select);
                        }
                        if (isappl)
                        {
                            xmlNodePtr cnl = caseNode->xmlChildrenNode;
                            while (cnl)
                            {
                                xmlAddChild(parent, clone(cnl, appl));
                                cnl = cnl->next;
                            }
                            break;
                        }

                    }
                    caseNode = caseNode->next;
                }
            }

        }
        else
            xmlAddChild(parent, clone(n, appl));

        n = n->next;
    }
    return parent;
}

class myparser
{
public:
    std::string documentId;
    std::string fileName;
    std::string title;
    HashSet *hidlist;
    Hashtable *keywords;
    Stringtable *helptexts;
private:
    HashSet extendedHelpText;
public:
    myparser(const std::string &indocumentId, const std::string &infileName, 
        const std::string &intitle) : documentId(indocumentId), fileName(infileName),
        title(intitle)
    {
        hidlist = new HashSet;
        keywords = new Hashtable;
        helptexts = new Stringtable;
    }
    void traverse( xmlNodePtr parentNode );
private:
    std::string dump(xmlNodePtr node);
};

std::string myparser::dump(xmlNodePtr node)
{
    std::string app;
    if (node->xmlChildrenNode)
    {
        xmlNodePtr list = node->xmlChildrenNode;
        while (list)
        {
            app += dump(list);
            list = list->next;
        }
    }
    if (xmlNodeIsText(node))
    {
        xmlChar *pContent = xmlNodeGetContent(node);
        app += std::string((const char*)pContent);
        xmlFree(pContent);
        // std::cout << app << std::endl;
    }
    return app;
}

void trim(std::string& str)
{
    std::string::size_type pos = str.find_last_not_of(' ');
    if(pos != std::string::npos)
    {
        str.erase(pos + 1);
        pos = str.find_first_not_of(' ');
        if(pos != std::string::npos)
            str.erase(0, pos);
    }
    else
        str.erase(str.begin(), str.end());
}

void myparser::traverse( xmlNodePtr parentNode )
{
    // traverse all nodes that belong to the parent
    xmlNodePtr test ;
    for (test = parentNode->xmlChildrenNode; test; test = test->next)
    {
        if (fileName.empty() && !strcmp((const char*)test->name, "filename")) 
        {
            xmlNodePtr node = test->xmlChildrenNode;
            if (xmlNodeIsText(node))
            {
                xmlChar *pContent = xmlNodeGetContent(node);
                fileName = std::string((const char*)pContent);
                xmlFree(pContent);
            }
        }
        else if (title.empty() && !strcmp((const char*)test->name, "title"))
        {
            title = dump(test);
            if (title.empty())
                title = "<notitle>";
        }
        else if (!strcmp((const char*)test->name, "bookmark"))
        {
            xmlChar *branchxml = xmlGetProp(test, (const xmlChar*)"branch");
            xmlChar *idxml = xmlGetProp(test, (const xmlChar*)"id");
            std::string branch((const char*)branchxml);
            std::string anchor((const char*)idxml);
            xmlFree (branchxml);
            xmlFree (idxml);

            std::string hid;

            if (branch.find("hid") == 0)
            {
                size_t index = branch.find('/');
                if (index != std::string::npos)
                {
                    hid = branch.substr(1 + index);
                    // one shall serve as a documentId
                    if (documentId.empty())
                        documentId = hid;
                    extendedHelpText.push_back(hid);
                    std::string foo = anchor.empty() ? hid : hid + "#" + anchor;
                    HCDBG(std::cerr << "hid pushback" << foo << std::endl);
                    hidlist->push_back( anchor.empty() ? hid : hid + "#" + anchor);
                }
                else
                    continue;
            }
            else if (branch.compare("index") == 0) 
            {
                LinkedList ll;

                for (xmlNodePtr nd = test->xmlChildrenNode; nd; nd = nd->next)
                {
                    if (strcmp((const char*)nd->name, "bookmark_value"))
                        continue;

                    std::string embedded;
                    xmlChar *embeddedxml = xmlGetProp(nd, (const xmlChar*)"embedded");
                    if (embeddedxml)
                    {
                        embedded = std::string((const char*)embeddedxml);
                        xmlFree (embeddedxml);
                        std::transform (embedded.begin(), embedded.end(), 
                            embedded.begin(), tolower);
                    }

                    bool isEmbedded = !embedded.empty() && embedded.compare("true") == 0;
                    if (isEmbedded)
                        continue;

                    std::string keyword = dump(nd);
                    size_t keywordSem = keyword.find(';');
                    if (keywordSem != std::string::npos)
                    {
                        std::string tmppre =
                                    keyword.substr(0,keywordSem);
                        trim(tmppre);
                        std::string tmppos =
                                    keyword.substr(1+keywordSem);
                        trim(tmppos);
                        keyword = tmppre + ";" + tmppos;
                    }
                    ll.push_back(keyword);
                }
                if (!ll.empty())
                    (*keywords)[anchor] = ll;
            }
            else if (branch.compare("contents") == 0) 
            {
                // currently not used
            }
        }
        else if (!strcmp((const char*)test->name, "ahelp"))
        {
            std::string text = dump(test);
            trim(text);
            std::string name;

            HashSet::const_iterator aEnd = extendedHelpText.end();
            for (HashSet::const_iterator iter = extendedHelpText.begin(); iter != aEnd;
                ++iter)
            {
                name = *iter;
                (*helptexts)[name] = text;
            }
            extendedHelpText.clear();
        }

        // traverse children
        traverse(test);
    }
}

bool HelpCompiler::compile( void ) throw( HelpProcessingException )
{
    // we now have the jaroutputstream, which will contain the document.
    // now determine the document as a dom tree in variable docResolved

    xmlDocPtr docResolvedOrg = getSourceDocument(inputFile);

    // now add path to the document
    // resolve the dom
    if (!docResolvedOrg)
    {
        impl_sleep( 3 );
        docResolvedOrg = getSourceDocument(inputFile);
        if( !docResolvedOrg )
        {
            std::stringstream aStrStream;
            aStrStream << "ERROR: file not existing: " << inputFile.native_file_string().c_str() << std::endl;
		    throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
        }
    }

    // now find all applications for which one has to compile
    std::string documentId;
    std::string fileName;
    std::string title;
    // returns all applications for which one has to compile
    HashSet applications = switchFind(docResolvedOrg);

    HashSet::const_iterator aEnd = applications.end();
    for (HashSet::const_iterator aI = applications.begin(); aI != aEnd; ++aI)
    {
        std::string appl = *aI;
        std::string modulename = appl;
        if (modulename[0] == 'S')
        {
            modulename = modulename.substr(1);
            std::transform(modulename.begin(), modulename.end(), modulename.begin(), tolower);
        }
        if (modulename != "DEFAULT" && modulename != module)
            continue;

        // returns a clone of the document with swich-cases resolved
        xmlNodePtr docResolved = clone(xmlDocGetRootElement(docResolvedOrg), appl);
        myparser aparser(documentId, fileName, title);
        aparser.traverse(docResolved);

        documentId = aparser.documentId;
        fileName = aparser.fileName;
        title = aparser.title;

        HCDBG(std::cerr << documentId << " : " << fileName << " : " << title << std::endl);

        xmlDocPtr docResolvedDoc = xmlCopyDoc(docResolvedOrg, false);
        xmlDocSetRootElement(docResolvedDoc, docResolved);

        if (modulename == "DEFAULT")
        {
            streamTable.dropdefault();
            streamTable.default_doc = docResolvedDoc;
            streamTable.default_hidlist = aparser.hidlist;
            streamTable.default_helptexts = aparser.helptexts;
            streamTable.default_keywords = aparser.keywords;
        }
        else if (modulename == module)
        {
            streamTable.dropappl();
            streamTable.appl_doc = docResolvedDoc;
            streamTable.appl_hidlist = aparser.hidlist;
            streamTable.appl_helptexts = aparser.helptexts;
            streamTable.appl_keywords = aparser.keywords;
        }
        else
        {
			std::stringstream aStrStream;
	        aStrStream << "ERROR: Found unexpected module name \"" << modulename
					   << "\" in file" << src.native_file_string().c_str() << std::endl;
			throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
        }
        
    } // end iteration over all applications

    streamTable.document_id = documentId;
    streamTable.document_path = fileName;
    streamTable.document_title = title;
    std::string actMod = module;
    if ( !bExtensionMode && !fileName.empty())
    {
        if (fileName.find("/text/") == 0)
        {
            int len = strlen("/text/");
            actMod = fileName.substr(len);
            actMod = actMod.substr(0, actMod.find('/'));
        }
    }
    streamTable.document_module = actMod;

    xmlFreeDoc(docResolvedOrg);
    return true;
}

namespace fs
{
	rtl_TextEncoding getThreadTextEncoding( void )
	{
		static bool bNeedsInit = true;
		static rtl_TextEncoding nThreadTextEncoding;
		if( bNeedsInit )
		{
			bNeedsInit = false;
			nThreadTextEncoding = osl_getThreadTextEncoding();
		}
		return nThreadTextEncoding;
	}

    void create_directory(const fs::path indexDirName)
    {
        HCDBG(
            std::cerr << "creating " << 
            rtl::OUStringToOString(indexDirName.data, RTL_TEXTENCODING_UTF8).getStr() 
            << std::endl
           );
        osl::Directory::createPath(indexDirName.data);
    }

    void rename(const fs::path &src, const fs::path &dest)
    {
        osl::File::move(src.data, dest.data);
    }

    void copy(const fs::path &src, const fs::path &dest)
    {
        osl::File::copy(src.data, dest.data);
    }

    bool exists(const fs::path &in)
    {
        osl::File tmp(in.data);
        return (tmp.open(osl_File_OpenFlag_Read) == osl::FileBase::E_None);
    }

    void remove(const fs::path &in)
    {
        osl::File::remove(in.data);
    }

    void removeRecursive(rtl::OUString const& _suDirURL)
    {
        {
            osl::Directory aDir(_suDirURL);
            aDir.open();
            if (aDir.isOpen())
            {
                osl::DirectoryItem aItem;
                osl::FileStatus aStatus(osl_FileStatus_Mask_FileName | osl_FileStatus_Mask_Attributes);
                while (aDir.getNextItem(aItem) == ::osl::FileBase::E_None)
                {
                    if (osl::FileBase::E_None == aItem.getFileStatus(aStatus) && 
                        aStatus.isValid(osl_FileStatus_Mask_FileName | osl_FileStatus_Mask_Attributes))
                    {
                        rtl::OUString suFilename = aStatus.getFileName();
                        rtl::OUString suFullFileURL;
                        suFullFileURL += _suDirURL;
                        suFullFileURL += rtl::OUString::createFromAscii("/");
                        suFullFileURL += suFilename;
                        
                        if (aStatus.getFileType() == osl::FileStatus::Directory)
                            removeRecursive(suFullFileURL);
                        else
                            osl::File::remove(suFullFileURL);
                    }
                }
                aDir.close();
            }
        }
        osl::Directory::remove(_suDirURL);
    }

    void remove_all(const fs::path &in)
    {
        removeRecursive(in.data);
    }
}

/* vi:set tabstop=4 shiftwidth=4 expandtab: */
