/***************************************************************************
*   Copyright (C) 2004-2009 by Thomas Fischer                             *
*   fischer@unix-ag.uni-kl.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.,                                       *
*   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
***************************************************************************/
#include <tqprocess.h>

#include <kkeydialog.h>
#include <kencodingfiledialog.h>
#include <tdeconfig.h>
#include <kurl.h>
#include <tdeactionclasses.h>
#include <kedittoolbar.h>
#include <kdebug.h>
#include <tdeaction.h>
#include <kstdaction.h>
#include <tdeio/netaccess.h>
#include <klibloader.h>
#include <tdemessagebox.h>
#include <kstatusbar.h>
#include <tdelocale.h>

#include "kbibtex_part.h"
#include "kbibtexshell.h"

KBibTeXShell::KBibTeXShell( TQWidget* parentWidget, const char* name )
        : KParts::MainWindow( parentWidget, name ), m_part( NULL ), m_parentWidget( parentWidget )
{
    // set the shell's ui resource file
    setXMLFile( "kbibtex_shell.rc" );

    // then, setup our actions
    setupActions();

    // and a status bar
    statusBar() ->show();

    // this routine will find and load our Part.  it finds the Part by
    // name which is a bad idea usually.. but it's alright in this
    // case since our Part is made for this Shell
    KLibFactory *factory = KLibLoader::self() ->factory( "libkbibtexpart" );
    if ( factory )
    {
        // now that the Part is loaded, we cast it to a Part to get
        // our hands on it
        m_part = static_cast<KParts::ReadWritePart *>( factory->create( this, "kbibtex_part", "KParts::ReadWritePart" ) );

        if ( m_part )
        {
            // tell the KParts::MainWindow that this is indeed the main widget
            setCentralWidget( m_part->widget() );

            // and integrate the part's GUI with the shell's
            createGUI( m_part );
        }

    }
    else
    {
        // if we couldn't find our Part, we exit since the Shell by
        // itself can't do anything useful
        KMessageBox::error( this, i18n( "Could not find our part!" ) );
        kapp->quit();
        // we return here, cause kapp->quit() only means "exit the
        // next time we enter the event loop...
        return ;
    }

    // apply the saved mainwindow settings, if any, and ask the mainwindow
    // to automatically save settings if changed: window size, toolbar
    // position, icon size, etc.
    setAutoSaveSettings();

    readConfig();

#ifdef HAVE_YAZ
    kdDebug() << "Using YAZ to access Z39.50 databases" << endl;
#else // HAVE_YAZ
    kdDebug() << "YAZ not linked to KBibTeX. No access to Z39.50 databases possible" << endl;
#endif // HAVE_YAZ

}

KBibTeXShell::~KBibTeXShell()
{
    // nothing
}

bool KBibTeXShell::openURL( const KURL& url )
{
    if ( url.isEmpty() )
        return false;

    // About this function, the style guide (
    // http://developer.kde.org/documentation/standards/kde/style/basics/index.html )
    // says that it should open a new window if the document is _not_
    // in its initial state.  This is what we do here.

    // If there is no part yet created, create new one...

    if ( m_part->url().isEmpty() && !m_part->isModified() )
    {
        if ( !m_part->openURL( url ) )
            return false;
    }
    else
    {
        KBibTeXShell *shell = new KBibTeXShell();

        if ( !shell->part() ->openURL( url ) )
            return false;
        else
            initializePart( shell->part() );
        shell->show();
    }

    m_recentFiles->addURL( url );
    return true;
}

KParts::ReadWritePart * KBibTeXShell::part()
{
    return m_part;
}

void KBibTeXShell::readConfig( TDEConfig *config )
{
    config->setGroup( "Session" );
    m_recentFiles->loadEntries( config );
    m_recentFiles->setEnabled( true ); // force enabling
    m_recentFiles->setToolTip( i18n( "Click to open a file\nClick and hold to open a recent file" ) );
}

void KBibTeXShell::writeConfig( TDEConfig *config )
{
    config->setGroup( "Session" );
    m_recentFiles->saveEntries( config );
    config->sync();
}

void KBibTeXShell::readConfig()
{
    TDEConfig * config = kapp->config();
    readConfig( config );
}

void KBibTeXShell::writeConfig()
{
    TDEConfig * config = kapp->config();
    writeConfig( config );
}

TQString KBibTeXShell::encoding()
{
    return "utf8";
}

void KBibTeXShell::slotAddRecentURL( const KURL&url )
{
    m_recentFiles->addURL( url );
}

void KBibTeXShell::setupActions()
{
    TDEAction * action;

    action = KStdAction::openNew( this, TQ_SLOT( slotFileNew() ), actionCollection() );
    action ->setToolTip( i18n( "Create a new window for a new BibTeX file" ) );
    TDEAction *actionOpen = KStdAction::open( this, TQ_SLOT( slotFileOpen() ), actionCollection() );
    actionOpen->setToolTip( i18n( "Open an existing BibTeX file" ) );

    m_recentFiles = KStdAction::openRecent( this, TQ_SLOT( slotFileOpen( const KURL& ) ), actionCollection() );
    m_recentFiles->setWhatsThis( i18n( "This lists files which you have opened recently, and allows you to easily open them again." ) );
    connect( m_recentFiles, TQ_SIGNAL( activated() ), actionOpen, TQ_SLOT( activate() ) );

    action = KStdAction::close( this, TQ_SLOT( slotFileClose() ), actionCollection() );
    action->setToolTip( i18n( "Close this KBibTeX window" ) );
    //     action = KStdAction::quit( kapp, TQ_SLOT( closeAllWindows() ), actionCollection() );
    //     action->setToolTip( i18n( "Close all windows and quit KBibTeX" ) );

    m_statusbarAction = KStdAction::showStatusbar( this, TQ_SLOT( optionsShowStatusbar() ), actionCollection() );
    m_statusbarAction->setToolTip( i18n( "Show or hide the window's status bar" ) );

    KStdAction::keyBindings( this, TQ_SLOT( optionsConfigureKeys() ), actionCollection() ) ->setToolTip( i18n( "Configure key bindings for KBibTeX" ) );
    KStdAction::configureToolbars( this, TQ_SLOT( optionsConfigureToolbars() ), actionCollection() ) ->setToolTip( i18n( "Configure the tool bar for KBibTeX" ) );

    connect( actionCollection(), TQ_SIGNAL( actionStatusText( const TQString & ) ), this, TQ_SLOT( slotActionStatusText( const TQString & ) ) );
    connect( actionCollection(), TQ_SIGNAL( clearStatusText( ) ), statusBar(), TQ_SLOT( clear() ) );
}

void KBibTeXShell::slotActionStatusText( const TQString &text )
{
    KStatusBar * stb = statusBar();

    if ( stb )
        stb->message( text );
}

void KBibTeXShell::saveProperties( TDEConfig* /*config*/ )
{
    // the 'config' object points to the session managed
    // config file.  anything you write here will be available
    // later when this app is restored
}

void KBibTeXShell::readProperties( TDEConfig* /*config*/ )
{
    // the 'config' object points to the session managed
    // config file.  this function is automatically called whenever
    // the app is being restored.  read in here whatever you wrote
    // in 'saveProperties'
}

void KBibTeXShell::optionsShowStatusbar()
{
    // this is all very cut and paste code for showing/hiding the
    // statusbar
    if ( m_statusbarAction->isChecked() )
        statusBar() ->show();
    else
        statusBar() ->hide();
}

void KBibTeXShell::optionsConfigureKeys()
{
    KKeyDialog dlg( false, this );
    TQPtrList<KXMLGUIClient> clients = guiFactory()->clients();
    for ( TQPtrListIterator<KXMLGUIClient> it( clients ); it.current(); ++it )
    {
        dlg.insert(( *it )->actionCollection() );
    }
    dlg.configure();
}

void KBibTeXShell::optionsConfigureToolbars()
{
    saveMainWindowSettings( TDEGlobal::config(), autoSaveGroup() );

    // use the standard toolbar editor
    KEditToolbar dlg( factory() );
    connect( &dlg, TQ_SIGNAL( newToolbarConfig() ),
             this, TQ_SLOT( applyNewToolbarConfig() ) );
    dlg.exec();
}

void KBibTeXShell::applyNewToolbarConfig()
{
    applyMainWindowSettings( TDEGlobal::config(), autoSaveGroup() );
}

bool KBibTeXShell::queryClose()
{
    if ( m_part && !m_part ->closeURL() )
        return false;

    writeConfig();

    return KParts::MainWindow::queryClose();
}

void KBibTeXShell::slotFileNew()
{
    // this slot is called whenever the File->New menu is selected,
    // the New shortcut is pressed (usually CTRL+N) or the New toolbar
    // button is clicked

    // About this function, the style guide (
    // http://developer.kde.org/documentation/standards/kde/style/basics/index.html )
    // says that it should open a new window if the document is _not_
    // in its initial state.  This is what we do here..
    if ( ! m_part->url().isEmpty() || m_part->isModified() )
    {
        ( new KBibTeXShell() ) ->show();
    };
}

/**
 * Show a file open dialog where a user can select one or several
 * files for opening.
 */
void KBibTeXShell::slotFileOpen()
{
    bool bibUtilsAvailable = checkExternalToolAvailable( "xml2bib" ) && checkExternalToolAvailable( "end2xml" );
    TQString startDir = ! m_part->url().isEmpty() ? m_part->url().url() : TQDir::currentDirPath();
    KURL mergeURL = KFileDialog::getOpenURL( startDir,  TQString( "*.bib *.ris" ) +
                    ( bibUtilsAvailable ? " *.xml *.ref *.refer *.rfr *.txt *.isi *.cgi" : "" ) + "|" + i18n( "Supported Bibliographies" ) + "\n*.bib|" + i18n( "BibTeX (*.bib)" ) + "\n*.ris|" + i18n( "Reference Manager (*.ris)" ) + ( bibUtilsAvailable ? "\n*.ref *.refer *.rfr *.txt|" + i18n( "EndNote (Refer format) (*.ref *.refer *.rfr *.txt)" ) + "\n*.isi *.cgi|" + i18n( "ISI Web of Knowledge (*.isi *.cgi)" ) + "\n*.xml|" + i18n( "MODS or EndNote XML (*.xml)" ) : "" ) + "\n*|" + i18n( "All files (*.*)" )
                    , widget() );
    slotFileOpen( mergeURL );
}


/**
 * Open a given url in a new window.
 */
void KBibTeXShell::slotFileOpen( const KURL& url )
{
    if ( url.isEmpty() ) return ;

    if ( !TDEIO::NetAccess::exists( url, true, this ) )
    {
        m_recentFiles->removeURL( url );
        KMessageBox::error( this, i18n( "The given file could not be read, check if it exists or if it is readable for the current user." ) );
        return ;
    }

    if ( m_part->url().isEmpty() && !m_part->isModified() )
        // we open the file in this window...
        openURL( url );
    else
    {
        // we open the file in a new window...
        KBibTeXShell * shell = new KBibTeXShell();
        if ( shell->openURL( url ) )
        {
            initializePart( shell->part() );
            shell->show();
        }
        else
        {
            KMessageBox::error( this, i18n( "Could not open file '%1'." ).arg( url.path() ) );
        }
    }

}

/**
 * Close currrent window
 */
void KBibTeXShell::slotFileClose()
{
    close();
}

void KBibTeXShell::initializePart( KParts::ReadWritePart* part )
{
    if ( part )
    {
        connect( static_cast<KBibTeXPart*>( part ), TQ_SIGNAL( signalAddRecentURL( const KURL & ) ), this, TQ_SLOT( slotAddRecentURL( const KURL& ) ) );
    }
}

bool KBibTeXShell::checkExternalToolAvailable( const TQString &binary )
{
    TQProcess *process = new TQProcess( binary );
    bool ok = process->start();
    ok &= process->normalExit();
    if ( process->isRunning() )
    {
        process->kill();
        ok = true;
    }
    delete process;
    return ok;
}


#include "kbibtexshell.moc"
