/***************************************************************************
 *   Copyright (C) 2004 by Alexander Dymo                                  *
 *   cloudtemple@mksat.net                                                 *
 *                                                                         *
 *   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 2 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, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.             *
 ***************************************************************************/
#include "dockdevtocplugin.h"

#include <unistd.h>

#include <tqdom.h>
#include <tqfile.h>
#include <tqfileinfo.h>
#include <tqdialog.h>

#include <kurl.h>
#include <tdeaboutdata.h>
#include <tdeconfig.h>
#include <tdelocale.h>
#include <tdelistview.h>
#include <tdestandarddirs.h>

#include <urlutil.h>
#include <kdevgenericfactory.h>
#include <kdevplugininfo.h>

#include "../../../../config.h"

class TOCDocumentationCatalogItem: public DocumentationCatalogItem
{
public:
    TOCDocumentationCatalogItem(const TQString &tocFile, DocumentationPlugin* plugin,
        TDEListView *parent, TDEListViewItem *after, const TQString &name)
        :DocumentationCatalogItem(plugin, parent, after, name), m_tocFile(tocFile)
    {
    }
    TOCDocumentationCatalogItem(const TQString &tocFile, DocumentationPlugin* plugin,
        DocumentationItem *parent, const TQString &name)
        :DocumentationCatalogItem(plugin, parent, name), m_tocFile(tocFile)
    {
    }
    TQString tocFile() const { return m_tocFile; }
    
private:
    TQString m_tocFile;
};


static const KDevPluginInfo data("dockdevtocplugin");
typedef KDevGenericFactory<DocKDevTOCPlugin> DocKDevTOCPluginFactory;
K_EXPORT_COMPONENT_FACTORY( libdockdevtocplugin, DocKDevTOCPluginFactory(data) )

DocKDevTOCPlugin::DocKDevTOCPlugin(TQObject* parent, const char* name,
    const TQStringList /*args*/)
    :DocumentationPlugin(DocKDevTOCPluginFactory::instance()->config(), parent, name)
{
    setCapabilities(Index);
    autoSetup();
}

DocKDevTOCPlugin::~DocKDevTOCPlugin()
{
}

TQString DocKDevTOCPlugin::pluginName() const
{
    return i18n("TDevelopTOC Documentation Collection");
}

DocumentationCatalogItem* DocKDevTOCPlugin::createCatalog(TDEListView* contents, TDEListViewItem *after, const TQString& title, const TQString& url)
{
    return new TOCDocumentationCatalogItem(url, this, contents, after, title);
}

TQPair<KFile::Mode, TQString> DocKDevTOCPlugin::catalogLocatorProps()
{
    return TQPair<KFile::Mode, TQString>(KFile::File, "*.toc");
}

TQString DocKDevTOCPlugin::catalogTitle(const TQString& url)
{
    TQFileInfo fi(url);
    if (!fi.exists())
        return TQString();

    TQFile f(url);
    if (!f.open(IO_ReadOnly))
        return TQString();
    
    TQDomDocument doc;
    if (!doc.setContent(&f) || (doc.doctype().name() != "tdeveloptoc"))
        return TQString();
    f.close();

    TQDomElement titleEl = doc.documentElement().namedItem("title").toElement();

    return titleEl.firstChild().toText().data();
}


TQStringList DocKDevTOCPlugin::fullTextSearchLocations()
{
    return TQStringList();
}

bool DocKDevTOCPlugin::needRefreshIndex(DocumentationCatalogItem* /*item*/)
{
    return false;
}

void DocKDevTOCPlugin::autoSetupPlugin()
{
    // Clear groups, to allow for re-autosetup calls
    config->deleteGroup("Index");
    config->deleteGroup("Index Settings");
    config->deleteGroup("Locations");
    config->deleteGroup("Search Settings");
    config->deleteGroup("TOC Settings");
    config->sync();
        
    TQStringList tocsDir = DocKDevTOCPluginFactory::instance()->dirs()->findAllResources("data", "kdevdocumentation/tocs/*.toc");
    
    for (TQStringList::const_iterator it = tocsDir.begin(); it != tocsDir.end(); ++it)
    {
        config->setGroup("Locations");
        config->writePathEntry(catalogTitle(*it), *it);
    }
    config->sync();
}

void DocKDevTOCPlugin::createIndex(IndexBox* index, DocumentationCatalogItem* item)
{
    TOCDocumentationCatalogItem *tocItem = dynamic_cast<TOCDocumentationCatalogItem *>(item);
    if (!tocItem)
        return;
    
    TQFileInfo fi(tocItem->tocFile());

    TQFile f(tocItem->tocFile());
    if (!f.open(IO_ReadOnly))
    {
        kdDebug(9002) << "Could not read" << tocItem->tocFile() << endl;
        return;
    }
    TQDomDocument doc;
    if (!doc.setContent(&f) || doc.doctype().name() != "tdeveloptoc")
    {
        kdDebug(9002) << "Not a valid tdeveloptoc file: " << tocItem->tocFile() << endl;
        return;
    }
    f.close();

    TQDomElement docEl = doc.documentElement();
    TQDomElement baseEl = docEl.namedItem("base").toElement();
    
    TQString base;
    if (!baseEl.isNull())
        base = baseEl.attribute("href", TQString());
    
    TQDomElement indexEl = docEl.namedItem("index").toElement();
    TQDomElement childEl = indexEl.firstChild().toElement();
    while (!childEl.isNull())
    {
        if (childEl.tagName() == "entry")
        {
            TQString name = childEl.attribute("name");
            TQString url = childEl.attribute("url");
            
            IndexItemProto *ii = new IndexItemProto(this, item, index, name, item->text(0));
            ii->addURL(KURL(constructURL(base, url)));
        }
        childEl = childEl.nextSibling().toElement();
    }
}

void DocKDevTOCPlugin::createTOC(DocumentationCatalogItem* item)
{
    TOCDocumentationCatalogItem *tocItem = dynamic_cast<TOCDocumentationCatalogItem *>(item);
    if (!tocItem)
        return;
    
    TQFileInfo fi(tocItem->tocFile());

    TQFile f(tocItem->tocFile());
    if (!f.open(IO_ReadOnly))
    {
        kdDebug(9002) << "Could not read" << tocItem->tocFile() << endl;
        return;
    }
    TQDomDocument doc;
    if (!doc.setContent(&f) || doc.doctype().name() != "tdeveloptoc")
    {
        kdDebug(9002) << "Not a valid tdeveloptoc file: " << tocItem->tocFile() << endl;
        return;
    }
    f.close();

    TQDomElement docEl = doc.documentElement();
    TQDomElement baseEl = docEl.namedItem("base").toElement();
    
    TQString base;
    if (!baseEl.isNull())
        base = baseEl.attribute("href", TQString());
    
    TQDomElement childEl = docEl.lastChild().toElement();
    addTocSect(tocItem, childEl, base, 1);
}

void DocKDevTOCPlugin::addTocSect(DocumentationItem *parent, TQDomElement childEl, const TQString &base, uint level)
{
    while (!childEl.isNull())
    {
        if (childEl.tagName() == TQString("tocsect%1").arg(level))
        {
            TQString name = childEl.attribute("name");
            TQString url = childEl.attribute("url");
            
            DocumentationItem *item = new DocumentationItem(level == 1 ? DocumentationItem::Book : DocumentationItem::Document, parent, name);
            item->setURL(KURL(constructURL(base, url)));

            TQDomElement grandchildEl = childEl.lastChild().toElement();
            addTocSect(item, grandchildEl, base, level+1);
        }
        childEl = childEl.previousSibling().toElement();
    }
}

void DocKDevTOCPlugin::setCatalogURL(DocumentationCatalogItem* item)
{
    TOCDocumentationCatalogItem *tocItem = dynamic_cast<TOCDocumentationCatalogItem *>(item);
    if (!tocItem)
        return;
    
    TQFileInfo fi(tocItem->tocFile());

    TQFile f(tocItem->tocFile());
    if (!f.open(IO_ReadOnly))
    {
        kdDebug(9002) << "Could not read" << tocItem->tocFile() << endl;
        return;
    }
    TQDomDocument doc;
    if (!doc.setContent(&f) || doc.doctype().name() != "tdeveloptoc")
    {
        kdDebug(9002) << "Not a valid tdeveloptoc file: " << tocItem->tocFile() << endl;
        return;
    }
    f.close();

    TQDomElement docEl = doc.documentElement();
    TQDomElement baseEl = docEl.namedItem("base").toElement();
    
    if (item->url().isEmpty())
    {
        if (baseEl.isNull())
            item->setURL(KURL());
        else
            item->setURL(KURL(constructURL(baseEl.attribute("href", TQString()),
                baseEl.attribute("url", TQString()))));
    }
}

TQString DocKDevTOCPlugin::constructURL(const TQString &base, const TQString &url)
{
    if (base.isEmpty() && !url.isEmpty())
        return url;
    if (!url.isEmpty())
        return base.endsWith("/") ? base + url : base + "/" + url;
    else
        return base;
}

#include "dockdevtocplugin.moc"
