/***************************************************************************
 *   Copyright (C) 2005-2007 by Rajko Albrecht                             *
 *   ral@alwins-world.de                                                   *
 *                                                                         *
 *   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 "tdesvn_part.h"
#include "tdesvnsettings.h"
#include "displaysettings_impl.h"
#include "dispcolorsettings_impl.h"
#include "revisiontreesettingsdlg_impl.h"
#include "diffmergesettings_impl.h"
#include "subversionsettings_impl.h"
#include "cmdexecsettings_impl.h"
#include "tdesvnview.h"
#include "commandline_part.h"
#include "version_check.h"
#include "url.h"
#include "helpers/ktranslateurl.h"
#include "helpers/sshagent.h"

#include <tdeinstance.h>
#include <tdeaction.h>
#include <kstdaction.h>
#include <tdefiledialog.h>
#include <kdebug.h>
#include <kbugreport.h>
#include <kxmlguifactory.h>
#include <tdeaboutapplication.h>
#include <tdeapplication.h>
#include <tdeconfigdialog.h>
#include <tdeaboutdata.h>
#include <tdelocale.h>

#include <tqcursor.h>
#include <tqpopupmenu.h>

//K_EXPORT_COMPONENT_FACTORY( tdesvnpart, tdesvnPartFactory )

extern "C" { KDESVN_EXPORT void *init_tdesvnpart() { return new tdesvnPartFactory; } }

static const char version[] = VERSION;

static const char description[] =
    I18N_NOOP("A Subversion Client for TDE (dynamic Part component)");

tdesvnPart::tdesvnPart( TQWidget *parentWidget, const char *widgetName,
                                  TQObject *parent, const char *name , const TQStringList&)
    : KParts::ReadOnlyPart(parent, name)
{
    init(parentWidget,widgetName,false);
}

tdesvnPart::tdesvnPart(TQWidget *parentWidget, const char *widgetName,
               TQObject *parent, const char *name,bool ownapp, const TQStringList&)
    : KParts::ReadOnlyPart(parent, name)
{
    init(parentWidget,widgetName,ownapp);
}

void tdesvnPart::init( TQWidget *parentWidget, const char *widgetName,bool full)
{
    m_aboutDlg = 0;
    TDEGlobal::locale()->insertCatalogue("tdesvn");
    // we need an instance
    setInstance( tdesvnPartFactory::instance() );
    m_browserExt = new KdesvnBrowserExtension( this );

    // this should be your custom internal widget
    m_view = new tdesvnView(actionCollection(),parentWidget,widgetName,full);

    // notify the part that this is our internal widget
    setWidget(m_view);

    // create our actions
    setupActions();
    // set our XML-UI resource file
#ifdef TESTING_PARTRC
    setXMLFile(TESTING_PARTRC);
    kdDebug()<<"Using test rc file in " << TESTING_PARTRC << endl;
#else
    setXMLFile("tdesvn_part.rc");
#endif
    connect(m_view,TQ_SIGNAL(sigShowPopup(const TQString&,TQWidget**)),this,TQ_SLOT(slotDispPopup(const TQString&,TQWidget**)));
    connect(m_view,TQ_SIGNAL(sigSwitchUrl(const KURL&)),this,TQ_SLOT(openURL(const KURL&)));
    connect(this,TQ_SIGNAL(refreshTree()),m_view,TQ_SLOT(refreshCurrentTree()));
    connect(m_view,TQ_SIGNAL(setWindowCaption(const TQString&)),this,TQ_SIGNAL(setWindowCaption(const TQString&)));
    connect(m_view,TQ_SIGNAL(sigUrlChanged( const TQString&)),this,TQ_SLOT(slotUrlChanged(const TQString&)));
    connect(this,TQ_SIGNAL(settingsChanged()),widget(),TQ_SLOT(slotSettingsChanged()));

    m_browserExt->setPropertiesActionEnabled(false);
}

tdesvnPart::~tdesvnPart()
{
    tdesvnPartFactory::instance()->config()->sync();
}

void tdesvnPart::slotUrlChanged(const TQString&url)
{
    m_url = url;
}

bool tdesvnPart::openFile()
{
    m_view->openURL(m_url);
    // just for fun, set the status bar
    emit setStatusBarText( m_url.prettyURL() );

    return true;
}

bool tdesvnPart::openURL(const KURL&url)
{

    KURL _url = helpers::KTranslateUrl::translateSystemUrl(url);

    _url.setProtocol(svn::Url::transformProtokoll(_url.protocol()));

    if (!_url.isValid()||!closeURL()) {
        return false;
    }
    m_url = _url;
    emit started(0);
    bool ret = m_view->openURL(m_url);
    if (ret) {
        emit completed();
        emit setWindowCaption(url.prettyURL());
    }
    return ret;
}

void tdesvnPart::slotFileProperties()
{
}

void tdesvnPart::slotDispPopup(const TQString&name,TQWidget**target)
{
    *target = hostContainer(name);
}

TDEAboutData* tdesvnPart::createAboutData()
{
    TQString m_Extratext = TQString(I18N_NOOP("Built with Subversion library: %1\n")).arg(svn::Version::linked_version());
    m_Extratext+=TQString(I18N_NOOP("Running Subversion library: %1")).arg(svn::Version::running_version());

    TDEAboutData*about = new TDEAboutData("tdesvnpart", I18N_NOOP("tdesvn Part"), version, description,
                     TDEAboutData::License_GPL, "(C) 2005-2007 Rajko Albrecht",0,
                         0, "ral@alwins-world.de");
    about->addAuthor( "Rajko Albrecht", 0, "ral@alwins-world.de" );
    about->setOtherText(m_Extratext.ascii());
    about->setHomepage("http://tdesvn.alwins-world.de/");
    about->setBugAddress("tdesvn-bugs@alwins-world.de");
    about->setTranslator(I18N_NOOP("tdesvn: NAME OF TRANSLATORS\\nYour names"),
        I18N_NOOP("tdesvn: EMAIL OF TRANSLATORS\\nYour emails"));
    return about;
}


/*!
    \fn tdesvnPart::setupActions()
 */
void tdesvnPart::setupActions()
{
    TDEToggleAction *toggletemp;

    toggletemp = new TDEToggleAction(i18n("Logs follow node changes"),TDEShortcut(),
            actionCollection(),"toggle_log_follows");
    toggletemp->setChecked(Kdesvnsettings::log_follows_nodes());
    connect(toggletemp,TQ_SIGNAL(toggled(bool)),this,TQ_SLOT(slotLogFollowNodes(bool)));

    toggletemp = new TDEToggleAction(i18n("Display ignored files"),TDEShortcut(),
            actionCollection(),"toggle_ignored_files");
    toggletemp->setChecked(Kdesvnsettings::display_ignored_files());
    connect(toggletemp,TQ_SIGNAL(toggled(bool)),this,TQ_SLOT(slotDisplayIgnored(bool)));


    toggletemp = new TDEToggleAction(i18n("Display unknown files"),TDEShortcut(),
            actionCollection(),"toggle_unknown_files");
    toggletemp->setChecked(Kdesvnsettings::display_unknown_files());
    connect(toggletemp,TQ_SIGNAL(toggled(bool)),this,TQ_SLOT(slotDisplayUnkown(bool)));

    toggletemp = new TDEToggleAction(i18n("Hide unchanged files"),TDEShortcut(),
                                   actionCollection(),"toggle_hide_unchanged_files");
    toggletemp->setChecked(Kdesvnsettings::hide_unchanged_files());
    connect(toggletemp,TQ_SIGNAL(toggled(bool)),this,TQ_SLOT(slotHideUnchanged(bool)));

    toggletemp = new TDEToggleAction(i18n("Work online"),TDEShortcut(),
                                   actionCollection(),"toggle_network");
    toggletemp->setChecked(Kdesvnsettings::network_on());
    connect(toggletemp,TQ_SIGNAL(toggled(bool)),this,TQ_SLOT(slotEnableNetwork(bool)));

    kdDebug()<<"Appname = " << (TQString)kapp->instanceName() << endl;

    TDEAction * t = KStdAction::preferences(this, TQ_SLOT(slotShowSettings()), actionCollection(),"tdesvnpart_pref");
    t->setText(i18n("&Configure %1...").arg("Kdesvn"));
    if (TQString(kapp->instanceName())!=TQString("tdesvn")) {
        (void)new TDEAction(i18n("&About tdesvn part"), "tdesvn", 0, this, TQ_SLOT(showAboutApplication()), actionCollection(), "help_about_tdesvnpart");
        (void)new TDEAction(i18n("Tdesvn &Handbook"), "help", 0, this, TQ_SLOT(appHelpActivated()), actionCollection(), "help_tdesvn");
        (void)new TDEAction(i18n("Send Bugreport for tdesvn"), 0, 0, this, TQ_SLOT(reportBug()), actionCollection(), "report_bug");
    }
    actionCollection()->setHighlightingEnabled(true);
}

void tdesvnPart::slotSshAdd()
{
    SshAgent ag;
    ag.addSshIdentities(true);
}

/*!
    \fn tdesvnPart::slotLogFollowNodes(bool)
 */
void tdesvnPart::slotLogFollowNodes(bool how)
{
    Kdesvnsettings::setLog_follows_nodes(how);
    Kdesvnsettings::writeConfig();
}


/*!
    \fn tdesvnPart::slotDiplayIgnored(bool)
 */
void tdesvnPart::slotDisplayIgnored(bool how)
{
    Kdesvnsettings::setDisplay_ignored_files(how);
    Kdesvnsettings::writeConfig();
    emit refreshTree();
}


/*!
    \fn tdesvnPart::slotDisplayUnknown(bool)
 */
void tdesvnPart::slotDisplayUnkown(bool how)
{
    Kdesvnsettings::setDisplay_unknown_files(how);
    Kdesvnsettings::writeConfig();
    emit refreshTree();
}

/*!
    \fn tdesvnPart::slotHideUnchanged(bool)
 */
void tdesvnPart::slotHideUnchanged(bool how)
{
    Kdesvnsettings::setHide_unchanged_files(how);
    Kdesvnsettings::writeConfig();
    emit refreshTree();
}

void tdesvnPart::slotEnableNetwork(bool how)
{
    Kdesvnsettings::setNetwork_on(how);
    Kdesvnsettings::writeConfig();
    emit settingsChanged();
}

/*!
    \fn tdesvnPart::closeURL()
 */
bool tdesvnPart::closeURL()
{
    m_url=KURL();
    m_view->closeMe();
    emit setWindowCaption("");
    return true;
}

KdesvnBrowserExtension::KdesvnBrowserExtension( tdesvnPart *p )
    : KParts::BrowserExtension( p, "KdesvnBrowserExtension" )
{
    TDEGlobal::locale()->insertCatalogue("tdesvn");
}

KdesvnBrowserExtension::~KdesvnBrowserExtension()
{

}


void KdesvnBrowserExtension::setPropertiesActionEnabled(bool enabled)
{
    emit enableAction("properties", enabled);
}


void KdesvnBrowserExtension::properties()
{
    static_cast<tdesvnPart*>(parent())->slotFileProperties();
}


/*!
    \fn tdesvnPart::reportBug()
 */
void tdesvnPart::reportBug()
{
  KBugReport dlg(m_view, true, createAboutData());
  dlg.exec();
}

/*!
    \fn tdesvnPart::showAboutApplication()
 */
void tdesvnPart::showAboutApplication()
{
    if (!m_aboutDlg) m_aboutDlg = new TDEAboutApplication(createAboutData(), (TQWidget *)0, (const char *)0, false);
    if(m_aboutDlg == 0)
        return;
    if(!m_aboutDlg->isVisible())
        m_aboutDlg->show();
    else
        m_aboutDlg->raise();
}


/*!
    \fn tdesvnPart::appHelpActivated()
 */
void tdesvnPart::appHelpActivated()
{
    kapp->invokeHelp(TQString(), "tdesvn");
}


/*!
    \fn tdesvnPart::slotShowSettings()
 */
void tdesvnPart::slotShowSettings()
{
    if (TDEConfigDialog::showDialog("tdesvnpart_settings")) {
        return;
    }
    TDEConfigDialog *dialog = new TDEConfigDialog(widget(),
         "tdesvnpart_settings",
         Kdesvnsettings::self(),
         KDialogBase::IconList);
    dialog->setHelp("setup","tdesvn");
    dialog->addPage(new DisplaySettings_impl(0,"general_items"),
        i18n("General"),"configure",i18n("General"),true);
    dialog->addPage(new SubversionSettings_impl(0,"subversion_items"),
        i18n("Subversion"),"tdesvn",i18n("Subversion Settings"),true);
    dialog->addPage(new DiffMergeSettings_impl(0,"diffmerge_items"),
        i18n("Diff & Merge"),"tdesvnmerge",i18n("Settings for diff and merge"),true);
    dialog->addPage(new DispColorSettings_impl(0,"color_items"),
        i18n("Colors"),"colorize",i18n("Color Settings"),true);
    dialog->addPage(new RevisiontreeSettingsDlg_impl(0,"revisiontree_items"),
        i18n("Revision tree"),"configure",i18n("Revision tree Settings"),true);
    dialog->addPage(new CmdExecSettings_impl(0,"cmdexec_items"),
        "TDEIO/"+i18n("Commandline"),"terminal",i18n("Settings for commandline and TDEIO execution"),true);

    connect(dialog,TQ_SIGNAL(settingsChanged()),this,TQ_SLOT(slotSettingsChanged()));
    dialog->show();
}


/*!
    \fn tdesvnPart::slotSettingsChanged()
 */
void tdesvnPart::slotSettingsChanged()
{
    TDEAction * temp;
    temp = actionCollection()->action("toggle_log_follows");
    if (temp) {
        ((TDEToggleAction*)temp)->setChecked(Kdesvnsettings::log_follows_nodes());
    }
    temp = actionCollection()->action("toggle_ignored_files");
    if (temp) {
        ((TDEToggleAction*)temp)->setChecked(Kdesvnsettings::display_ignored_files());
    }
#if 0
    /// not needed this momenta
    temp = actionCollection()->action("toggle_unknown_files");
    if (temp) {
        ((TDEToggleAction*)temp)->setChecked(tdesvnPart_Prefs::self()->mdisp_unknown_files);
    }
#endif
    emit settingsChanged();
}

/*
 * we may not use generic factory 'cause we make some specials */
TDEInstance*  cFactory::s_instance = 0L;
TDEAboutData* cFactory::s_about = 0L;
commandline_part* cFactory::s_cline = 0L;

KParts::Part* cFactory::createPartObject( TQWidget *parentWidget, const char *widgetName,
                                                        TQObject *parent, const char *name,
                                                        const char *classname, const TQStringList &args )
{
    Q_UNUSED(classname);
    // Create an instance of our Part
    return new tdesvnPart( parentWidget, widgetName, parent, name, args );
}

KParts::Part* cFactory::createAppPart( TQWidget *parentWidget, const char *widgetName,
                                          TQObject *parent, const char *name,
                                          const char *classname, const TQStringList &args )
{
    Q_UNUSED(classname);
    // Create an instance of our Part
    tdesvnPart* obj = new tdesvnPart( parentWidget, widgetName, parent, name, false, args);
    emit objectCreated( obj );
    return obj;
}

cFactory::~cFactory()
{
    delete s_instance;
    delete s_about;
    delete s_cline;

    s_instance = 0L;
    s_cline = 0L;
}

TDEInstance* cFactory::instance()
{
    if( !s_instance ) {
        s_about = tdesvnPart::createAboutData();
        s_instance = new TDEInstance(s_about);
    }
    return s_instance;
}

commandline_part*cFactory::createCommandIf(TQObject*parent,const char*name, TDECmdLineArgs *args)
{
    if (!s_cline) {
        // no emit of creation - we will delete this object in destructor
        s_cline = new commandline_part(parent,name,args);
    }
    return s_cline;
}

#include "tdesvn_part.moc"
