/***************************************************************************
 *   Copyright (C) 2003 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.                                   *
 ***************************************************************************/

#include <tqlistview.h>
#include <tqpushbutton.h>
#include <tqdir.h>
#include <tqfileinfo.h>
#include <tqtabwidget.h>
#include <tqdom.h>
#include <tqfile.h>
#include <tqtextstream.h>
#include <tqcheckbox.h>
#include <klineedit.h>
#include <tqlabel.h>

#include <kstandarddirs.h>
#include <tdeio/netaccess.h>
#include <kurlrequester.h>
#include <kicondialog.h>
#include <tdelocale.h>
#include <tdemessagebox.h>
#include <kiconloader.h>
#include <tdeversion.h>

#include "fctypeedit.h"
#include "fctemplateedit.h"
#include "domutil.h"
#include "fcconfigwidget.h"
#include "filecreate_part.h"
#include "filecreate_filetype.h"
#include "kdevproject.h"
#include "kdevpartcontroller.h"


FCConfigWidget::FCConfigWidget(FileCreatePart * part, bool global, TQWidget *parent, const char *name):
    FCConfigWidgetBase(parent, name), m_part(part), m_global(global)
{
    fc_view->setSorting(-1, FALSE);
    fcglobal_view->setSorting(-1, FALSE);

    if (m_global)
    {
        loadGlobalConfig(fc_view);
        fc_tabs->setTabLabel(tab1, i18n("Global Types") );
        fc_tabs->setTabEnabled(tab2, false);
        fc_tabs->setTabEnabled(tab3, false);
        delete tab2;
        delete tab3;
    }
    else
    {
        loadGlobalConfig(fcglobal_view, true);
        loadProjectConfig(fc_view);
        loadProjectTemplates(fctemplates_view);
        templatesDir_label->setText(i18n("Project templates in ") + m_part->project()->projectDirectory() + "/templates");
    }

    m_globalfiletypes.setAutoDelete(true);
    m_projectfiletypes.setAutoDelete(true);
    m_projectfiletemplates.setAutoDelete(true);
}

FCConfigWidget::~FCConfigWidget()
{
}

void FCConfigWidget::accept()
{
    if (m_global) {
        saveGlobalConfig();
    }
    else
        saveProjectConfig();

    m_part->m_filetypes.clear();
    m_part->slotProjectOpened();

    for (TQValueList<KURL>::iterator it = urlsToEdit.begin(); it != urlsToEdit.end(); ++it )
    {
        m_part->partController()->editDocument(*it);
    }
}

void FCConfigWidget::loadGlobalConfig(TQListView *view, bool checkmarks)
{
    TQString globalXMLFile = ::locate("data", "kdevfilecreate/template-info.xml");
    TQDomDocument globalDom;
    if (!globalXMLFile.isNull() &&
        DomUtil::openDOMFile(globalDom,globalXMLFile)) {
        m_part->readTypes(globalDom, m_globalfiletypes, false);
    }


    loadFileTypes(m_globalfiletypes, view, checkmarks);

    if (checkmarks)
    {
        TQDomElement useGlobalTypes =
            DomUtil::elementByPath(*(m_part->projectDom()),"/kdevfilecreate/useglobaltypes");
        for(TQDomNode node = useGlobalTypes.firstChild(); !node.isNull();node=node.nextSibling())
        {
            if (node.isElement() && node.nodeName()=="type")
            {
                TQDomElement element = node.toElement();
                TQString ext = element.attribute("ext");
                TQString subtyperef = element.attribute("subtyperef");
                if (subtyperef.isNull())
                {
                    TQListViewItem *it = view->findItem(ext, 0);
                    if (it)
                    {
                        ((TQCheckListItem*)it)->setOn(true);

                        TQListViewItem *lastChild = it->firstChild();
                        while ( lastChild )
                        {
                            ((TQCheckListItem*)lastChild)->setOn(true);
                            lastChild = lastChild->nextSibling();
                        }
                    }
                }
                else
                {
                    TQListViewItem *it = view->findItem(subtyperef, 0);
                    if (it)
                        ((TQCheckListItem*)it)->setOn(true);
                }
            }
        }
    }
}

void FCConfigWidget::loadProjectConfig(TQListView *view)
{
    m_part->readTypes( *(m_part->projectDom()), m_projectfiletypes, false );
    loadFileTypes(m_projectfiletypes, view, false);
}

void FCConfigWidget::loadProjectTemplates(TQListView *view)
{
    TQDir templDir( m_part->project()->projectDirectory() + "/templates/" );
    templDir.setFilter( TQDir::Files );
    const TQFileInfoList * list = templDir.entryInfoList();
    if( list ){
      TQFileInfoListIterator it( *list );
      TQFileInfo *fi;
      while ( (fi = it.current()) != 0 ) {
        FileType * filetype;
        filetype = new FileType;
        //name shall be "" for proper configuration
        filetype->setName( "" );
        filetype->setExt( fi->fileName() );
        m_projectfiletemplates.append(filetype);
        filetype->setEnabled(false);
        ++it;
      }
    }
    loadFileTypes(m_projectfiletemplates, view, false);
}


void FCConfigWidget::saveGlobalConfig()
{
    TQDomDocument globalDom;
    TQDomElement  element = globalDom.createElement("kdevelop" );
    globalDom.appendChild(element);
    TQDomElement  apPart  = globalDom.createElement("kdevfilecreate");
    element.appendChild(apPart);
    TQDomElement fileTypes = globalDom.createElement( "filetypes" );
    apPart.appendChild( fileTypes );

    saveConfiguration(globalDom, fileTypes, true);

    TQFile config( TDEGlobal::dirs()->saveLocation("data", "kdevfilecreate/", true) + "template-info.xml" );
    config.open(IO_WriteOnly | IO_Truncate);
    TQTextStream stream(&config);
    stream << "<?xml version = '1.0'?>";
    stream << globalDom.toString();
    config.close();
}

void FCConfigWidget::saveProjectConfig()
{
    TQDomDocument dom     = *m_part->projectDom( );
    TQDomElement  element = dom.documentElement( );
    TQDomElement  apPart  = element.namedItem( "kdevfilecreate" ).toElement( );
    if( apPart.isNull( ) )
    {
        apPart = dom.createElement( "kdevfilecreate" );
        element.appendChild( apPart );
    }


    // project template configuration

    TQDomElement projectTypes = apPart.namedItem( "filetypes" ).toElement( );
    apPart.removeChild(projectTypes);
    projectTypes = dom.createElement( "filetypes" );
    apPart.appendChild( projectTypes );

    saveConfiguration(dom, projectTypes, false);


    // global template usage

    TQDomElement globalTypes = apPart.namedItem( "useglobaltypes" ).toElement( );
    apPart.removeChild(globalTypes);
    globalTypes = dom.createElement( "useglobaltypes" );
    apPart.appendChild( globalTypes );

    TQListViewItemIterator it( fcglobal_view );
    for( ; it.current( ); ++it ){
        if (!it.current()->parent())
        {
            TQCheckListItem *chit = dynamic_cast<TQCheckListItem*>(it.current());
            if ( !chit ) continue;
            if (chit->isOn())
            {
                TQDomElement type = dom.createElement( "type" );
                type.setAttribute( "ext", chit->text(0) );
                globalTypes.appendChild( type );
            }
            else
            {
                TQListViewItem *lastChild = chit->firstChild();
                while ( lastChild )
                {
                    TQCheckListItem *chsit = dynamic_cast<TQCheckListItem*>(lastChild);
                    if ( (chsit) && (chsit->isOn()))
                    {
                        TQDomElement type = dom.createElement( "type" );
                        type.setAttribute( "ext", chit->text(0) );
                        type.setAttribute( "subtyperef", chsit->text(0) );
                        globalTypes.appendChild( type );
                    }

                    lastChild = lastChild->nextSibling();
                }
            }
        }
    }


    // project template files

    //check for new templates and those with location changed
    TQListViewItemIterator it2(fctemplates_view);
    while (it2.current())
    {
        if (!it2.current()->text(1).isEmpty())
        {
            TQString dest;
            dest = m_part->project()->projectDirectory() + "/templates/";
            if (it2.current()->text(1) == "create")
                copyTemplate(TQString(), dest, it2.current()->text(0));
            else
                copyTemplate(it2.current()->text(1), dest, it2.current()->text(0));
        }
        ++it2;
    }
}

void FCConfigWidget::saveConfiguration(TQDomDocument &dom, TQDomElement &element, bool global)
{
    TQListViewItemIterator it( fc_view );
    for( ; it.current( ); ++it ){
        if (!it.current()->parent())
        {
            TQDomElement type = dom.createElement( "type" );
            type.setAttribute( "ext", it.current()->text(0) );
            type.setAttribute( "name", it.current()->text(1) );
            if (it.current()->childCount() > 0)
                type.setAttribute( "create", "no");
            else
                type.setAttribute( "create", "template");
            type.setAttribute( "icon", it.current()->text(2) );

            TQDomElement edescr = dom.createElement("descr");
            type.appendChild(edescr);
            TQDomText descr = dom.createTextNode( it.current()->text(3) );
            edescr.appendChild(descr);

            if (!it.current()->text(4).isEmpty())
            {
                TQString dest;
                if (global)
                    dest = TDEGlobal::dirs()->saveLocation("data", "/kdevfilecreate/file-templates/", true);
                else
                    dest = m_part->project()->projectDirectory() + "/templates/";
                if (it.current()->text(4) == "create")
                    copyTemplate(TQString(), dest, it.current()->text(0));
                else
                    copyTemplate(it.current()->text(4), dest, it.current()->text(0));
            }


            TQListViewItem *lastChild = it.current()->firstChild();
            while ( lastChild )
            {
                TQDomElement subtype = dom.createElement( "subtype" );
                subtype.setAttribute( "ref", lastChild->text(0) );
                subtype.setAttribute( "name", lastChild->text(1) );
                subtype.setAttribute( "icon", lastChild->text(2) );

                TQDomElement edescr = dom.createElement("descr");
                subtype.appendChild(edescr);
                TQDomText descr = dom.createTextNode( lastChild->text(3) );
                edescr.appendChild(descr);

                if (!lastChild->text(4).isEmpty())
                {
                    TQString dest;
                    if (global)
                        dest = TDEGlobal::dirs()->saveLocation("data", "/kdevfilecreate/file-templates/", true);
                    else
                        dest = m_part->project()->projectDirectory() + "/templates/";
                    if (lastChild->text(4) == "create")
                        copyTemplate(TQString(), dest, it.current()->text(0) + "-" + lastChild->text(0));
                    else
                        copyTemplate(lastChild->text(4), dest, it.current()->text(0) + "-" + lastChild->text(0));
                }

                type.appendChild( subtype );
                lastChild = lastChild->nextSibling();
            }

            element.appendChild( type );
        }
    }
}

void FCConfigWidget::copyTemplate(TQString templateUrl, TQString dest, TQString destName)
{
    if (templateUrl.isEmpty())
    {
        TQDir d(dest);
        if (!d.exists())
            d.mkdir(dest);

        TQFile f(dest + destName);
        f.open(IO_WriteOnly);
        f.close();
    }
    else
    {
        KURL destDir;
        destDir.setPath(dest);
        if (!TDEIO::NetAccess::exists(destDir, false, 0 ))
            TDEIO::NetAccess::mkdir(destDir);

        KURL destination;
        destination.setPath(dest + destName);

        TDEIO::NetAccess::upload(templateUrl, destination);
    }
}

void FCConfigWidget::loadFileTypes(TQPtrList<FileCreate::FileType> list, TQListView *view, bool checkmarks)
{
    FileType *ft;

    for( ft = list.last(); ft; ft = list.prev())
    for( int i = list.count() - 1; i >= 0; --i)
    {
        if ( (ft = list.at(i)) )
        {
            TQListViewItem *it;
            if (!checkmarks)
                it = new TQListViewItem(view);
            else
                it = new TQCheckListItem(view, "", TQCheckListItem::CheckBox);

            it->setText(0, ft->ext());
            it->setText(1, ft->name());
            it->setText(2, ft->icon());
            it->setText(3, ft->descr());
            it->setText(4, "");

            FileType *sft;
            for( int j = ft->subtypes().count() - 1; j >= 0; --j)
            {
                if ( (sft = ft->subtypes().at(j)) )
                {
                    TQListViewItem *sit;
                    if (!checkmarks)
                        sit = new TQListViewItem(it);
                    else
                        sit = new TQCheckListItem(it, "", TQCheckListItem::CheckBox);

                    sit->setText(0, sft->subtypeRef());
                    sit->setText(1, sft->name());
                    sit->setText(2, sft->icon());
                    sit->setText(3, sft->descr());
                    sit->setText(4, "");
                }
            }
        }
    }
}

void FCConfigWidget::removetemplate_button_clicked( )
{
    if (fctemplates_view->currentItem())
    {
        KURL removedTemplate;
        removedTemplate.setPath(m_part->project()->projectDirectory() + "/templates/" + fctemplates_view->currentItem()->text(0));
        TDEIO::NetAccess::del(removedTemplate);
        TQListViewItem *it = fctemplates_view->currentItem();
        if (it->itemBelow())
        {
            fc_view->setSelected(it->itemBelow(), true);
            fc_view->setCurrentItem(it->itemBelow());
        }
        else if (it->itemAbove())
        {
            fc_view->setSelected(it->itemAbove(), true);
            fc_view->setCurrentItem(it->itemAbove());
        }
        delete it;
    }
}

void FCConfigWidget::copyToProject_button_clicked()
{
    TQListViewItem *it = fcglobal_view->currentItem();
    if (it)
    {
        TQListViewItem *it_copy_parent = 0;
        TQString destParent;
        if (it->parent())
        {
            it_copy_parent = new TQListViewItem(fc_view, it->parent()->text(0),
                it->parent()->text(1),
                it->parent()->text(2),
                it->parent()->text(3),
                locate("data", "kdevfilecreate/file-templates/"+ it->parent()->text(0)));
            destParent += it->parent()->text(0) + "-";
            TQCheckListItem *chk = dynamic_cast<TQCheckListItem*>(it->parent());
            if (chk)
                chk->setOn(false);
        }
        TQListViewItem *it_copy = 0;
        if (it_copy_parent)
            it_copy = new TQListViewItem(it_copy_parent, it->text(0),
                it->text(1),
                it->text(2),
                it->text(3),
                locate("data", "kdevfilecreate/file-templates/"+destParent + it->text(0)));
        else
            it_copy = new TQListViewItem(fc_view, it->text(0),
                it->text(1),
                it->text(2),
                it->text(3),
                locate("data", "kdevfilecreate/file-templates/" +destParent+ it->text(0)));
        TQCheckListItem *chk = dynamic_cast<TQCheckListItem*>(it);
        if (chk)
            chk->setOn(false);
        fc_view->setSelected(it_copy, true);
        fc_view->setCurrentItem(it_copy);
        TQListViewItem * it_child = it->firstChild();
        while( it_child ) {
            new TQListViewItem(it_copy, it_child->text(0),
                it_child->text(1),
                it_child->text(2),
                it_child->text(3),
                locate("data", "kdevfilecreate/file-templates/"+ it_copy->text(0) + "-" + it_child->text(0)));
            TQCheckListItem *chk_child = dynamic_cast<TQCheckListItem*>(it_child);
            if (chk_child)
                chk_child->setOn(false);
            it_child = it_child->nextSibling();
        }
    }
}

void FCConfigWidget::newtype_button_clicked()
{
    FCTypeEdit *te = new FCTypeEdit();
    if (te->exec() == TQDialog::Accepted )
    {
        TQListViewItem *it = new TQListViewItem(fc_view, te->typeext_edit->text(),
            te->typename_edit->text(),
            te->icon_url->icon(),
            te->typedescr_edit->text(),
            te->template_url->url().isEmpty() ? TQString("create") : te->template_url->url());
        fc_view->setSelected(it, true);
        fc_view->setCurrentItem(it);
    }
    delete te;
}

void FCConfigWidget::newsubtype_button_clicked()
{
    if (fc_view->currentItem() && (!fc_view->currentItem()->parent()))
    {
        FCTypeEdit *te = new FCTypeEdit(this);
        if (te->exec() == TQDialog::Accepted )
        {
            /*TQListViewItem *it =*/(void) new TQListViewItem(fc_view->currentItem(),
                te->typeext_edit->text(),
                te->typename_edit->text(),
                te->icon_url->icon(),
                te->typedescr_edit->text(),
                te->template_url->url().isEmpty() ? TQString("create") : te->template_url->url());
            fc_view->currentItem()->setOpen(true);
        }
        delete te;
    }
}

void FCConfigWidget::remove_button_clicked()
{
    if (fc_view->currentItem())
    {
        TQListViewItem *it = fc_view->currentItem();
        if (it->itemBelow())
        {
            fc_view->setSelected(it->itemBelow(), true);
            fc_view->setCurrentItem(it->itemBelow());
        }
        else if (it->itemAbove())
        {
            fc_view->setSelected(it->itemAbove(), true);
            fc_view->setCurrentItem(it->itemAbove());
        }
        delete it;
    }
}


void FCConfigWidget::moveup_button_clicked()
{
    TQListViewItem *i = fc_view->currentItem();
    if ( !i )
        return;

    TQListViewItemIterator it( i );
    TQListViewItem *parent = i->parent();
    --it;
    while ( it.current() ) {
        if ( it.current()->parent() == parent )
            break;
        --it;
    }

    if ( !it.current() )
        return;
    TQListViewItem *other = it.current();

    other->moveItem( i );
}


void FCConfigWidget::movedown_button_clicked()
{
    TQListViewItem *i = fc_view->currentItem();
    if ( !i )
        return;

    TQListViewItemIterator it( i );
    TQListViewItem *parent = i->parent();
    it++;
    while ( it.current() ) {
        if ( it.current()->parent() == parent )
            break;
        it++;
    }

    if ( !it.current() )
        return;
    TQListViewItem *other = it.current();

    i->moveItem( other );
}


void FCConfigWidget::edittype_button_clicked()
{
    TQListViewItem *it = fc_view->currentItem();
    if ( it )
    {
        FCTypeEdit *te = new FCTypeEdit(this);

        te->typeext_edit->setText(it->text(0));
        te->typename_edit->setText(it->text(1));
        te->icon_url->setIcon(it->text(2));
        te->typedescr_edit->setText(it->text(3));
        if (it->text(4) != "create")
            te->template_url->setURL(it->text(4));

        if (te->exec() == TQDialog::Accepted )
        {
            it->setText(0, te->typeext_edit->text());
            it->setText(1, te->typename_edit->text());
            it->setText(2, te->icon_url->icon());
            it->setText(3, te->typedescr_edit->text());
            if ((te->template_url->url() == "") && ((it->text(4) == "create")))
                it->setText(4, "create");
            else
                it->setText(4, te->template_url->url());
        }
    }
}


void FCConfigWidget::newtemplate_button_clicked()
{
    FCTemplateEdit *te = new FCTemplateEdit;
    if (te->exec() == TQDialog::Accepted)
    {
        /*TQListViewItem *it =*/(void) new TQListViewItem(fctemplates_view, te->templatename_edit->text(),
            te->template_url->url().isEmpty() ? TQString("create") : te->template_url->url());
    }
}


void FCConfigWidget::edittemplate_button_clicked()
{
    TQListViewItem *it;
    if ( (it = fctemplates_view->currentItem()) )
    {
        FCTemplateEdit *te = new FCTemplateEdit;
        te->templatename_edit->setText(it->text(0));
        te->templatename_edit->setEnabled(false);
        if (te->exec() == TQDialog::Accepted)
        {
            if ((te->template_url->url() == "") && ((it->text(1) == "create")))
                it->setText(1, "create");
            else
                it->setText(1, te->template_url->url());
        }
    }
}

void FCConfigWidget::edit_template_content_button_clicked( )
{
    if (fctemplates_view->currentItem())
    {
        TQFileInfo fi(m_part->project()->projectDirectory() + "/templates/" + fctemplates_view->currentItem()->text(0));
        KURL content;
        content.setPath(m_part->project()->projectDirectory() + "/templates/" + fctemplates_view->currentItem()->text(0));
        if (fi.exists())
            m_part->partController()->editDocument(content);
        else
        {
            KMessageBox::information(this, i18n("Requested template does not exist yet.\nIt will be opened immediately after accepting the configuration dialog."), TQString(), "Edit template content warning");
            fctemplates_view->currentItem()->setPixmap(0, SmallIcon("edit"));
            urlsToEdit.append(content);
        }
    }
}

void FCConfigWidget::edit_type_content_button_clicked( )
{
    if (!fc_view->currentItem())
        return;
    TQListViewItem *it = fc_view->currentItem();
    TQString type_name = it->text(0);
    if (it->parent())
        type_name.prepend(it->parent()->text(0) + "-");
    if (!m_global)
    {
        TQString typePath = m_part->project()->projectDirectory() + "/templates/" + type_name;
        KURL content;
        content.setPath(typePath);
        if (it->text(4).isEmpty())
            m_part->partController()->editDocument(content);
        else
        {
            if (it->text(4) == "create")
                KMessageBox::information(this, i18n("Template for the selected file type does not exist yet.\nIt will be opened immediately after accepting the configuration dialog."), TQString(), "Edit type template content warning");
            else
                KMessageBox::information(this, i18n("Template for the selected file type has been changed.\nIt will be opened immediately after accepting the configuration dialog."), TQString(), "Edit type template content warning");
            fc_view->currentItem()->setPixmap(0, SmallIcon("edit"));
            urlsToEdit.append(content);
        }
    }
    else
    {
        TQString dest = TDEGlobal::dirs()->saveLocation("data", "/kdevfilecreate/file-templates/", true);
        TQString typePath = dest + type_name;
        KURL content;
        content.setPath(typePath);
        if (it->text(4).isEmpty())
        {
            TQFileInfo fi(dest+type_name);
            if (!fi.exists())
                copyTemplate(locate("data", "kdevfilecreate/file-templates/" + type_name), dest, type_name);
            m_part->partController()->editDocument(content);
        }
        else
        {
            if (it->text(4) == "create")
                KMessageBox::information(this, i18n("Template for the selected file type does not exist yet.\nIt will be opened immediately after accepting the configuration dialog."), TQString(), "Edit global type template content warning");
            else
                KMessageBox::information(this, i18n("Template for the selected file type has been changed.\nIt will be opened immediately after accepting the configuration dialog."), TQString(), "Edit global type template content warning");
            fc_view->currentItem()->setPixmap(0, SmallIcon("edit"));
            urlsToEdit.append(content);
        }
    }
}

#include "fcconfigwidget.moc"
