/***************************************************************************
 *   Copyright (C) 2003 by Mario Scalas                                    *
 *   mario.scalas@libero.it                                                *
 *                                                                         *
 *   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 <tqcheckbox.h>
#include <tqpushbutton.h>
#include <tqcombobox.h>
#include <tqfile.h>
#include <tqtextstream.h>

#include <tdelistview.h>
#include <kurlrequester.h>
#include <tdelocale.h>
#include <tdemessagebox.h>
#include <tdefiledialog.h>
#include <kcursor.h>
#include <kdebug.h>
#include <tdeapplication.h>
#include <klineedit.h>

#include <dcopref.h>
#include <cvsjob_stub.h>
#include <repository_stub.h>
#include <cvsservice_stub.h>

#include "checkoutdialogbase.h"

#include "checkoutdialog.h"

///////////////////////////////////////////////////////////////////////////////
// Constants
///////////////////////////////////////////////////////////////////////////////

const TQString SSS( ":" );  // Server String Separator :)

///////////////////////////////////////////////////////////////////////////////
// class ModuleListViewItem
///////////////////////////////////////////////////////////////////////////////

class ModuleListViewItem : public TDEListViewItem
{
public:
    ModuleListViewItem( TDEListView *listview,
        const TQString &moduleAlias, const TQString &moduleRealPath )
        : TDEListViewItem( listview )
    {
        setAlias( moduleAlias );
        setRealPath( moduleRealPath );
    }

    void setAlias( const TQString &aName ) { setText( 0, aName); }
    TQString alias() const { return text(0); }
    void setRealPath( const TQString &aRealPath ) { setText(1, aRealPath); }
    TQString realPath() const { return text(1); }

//    virtual TQString text() const { return name(); }
};

///////////////////////////////////////////////////////////////////////////////
// class CheckoutDialog
///////////////////////////////////////////////////////////////////////////////

CheckoutDialog::CheckoutDialog( CvsService_stub *cvsService,
    TQWidget *parent, const char *name, WFlags ) :
    DCOPObject( "CheckoutDialogDCOPIface" ),
    KDialogBase( parent, name? name : "checkoutdialog", true, i18n("CVS Checkout"),
        Ok | Cancel, Ok, true ),
    m_service( cvsService ), m_job( 0 )
{
    m_base = new CheckoutDialogBase( this, "checkoutdialogbase" );
    setMainWidget( m_base );

    connect( m_base->fetchModulesButton, TQ_SIGNAL(clicked()),
        this, TQ_SLOT(slotFetchModulesList()) );
    connect( m_base->modulesListView, TQ_SIGNAL(executed(TQListViewItem*)),
        this, TQ_SLOT(slotModuleSelected(TQListViewItem*)) );

    // Avoid displaying 'file:/' when displaying the file
    m_base->workURLRequester->setShowLocalProtocol( false );
    m_base->workURLRequester->setMode( KFile::Directory );

	// Grab the entries from $HOME/.cvspass
	fetchUserCvsRepositories();
	// And suggest to use the default projects dir set in KDevelop's preferences
    TDEConfig *config = kapp->config();
	config->setGroup("General Options");
    TQString defaultProjectsDir = config->readPathEntry("DefaultProjectsDir", TQDir::homeDirPath()+"/");
	setWorkDir( defaultProjectsDir );
}

///////////////////////////////////////////////////////////////////////////////

CheckoutDialog::~CheckoutDialog()
{
    delete m_job;
}

///////////////////////////////////////////////////////////////////////////////

TQString CheckoutDialog::serverPath() const
{
	return m_base->serverPaths->currentText();
}

///////////////////////////////////////////////////////////////////////////////

void CheckoutDialog::fillServerPaths( const TQStringList &serverPaths )
{
    m_base->serverPaths->insertStringList( serverPaths );
}

///////////////////////////////////////////////////////////////////////////////

TQString CheckoutDialog::workDir() const
{
    return m_base->workURLRequester->url();
}

///////////////////////////////////////////////////////////////////////////////

void CheckoutDialog::setWorkDir( const TQString &aDir )
{
    m_base->workURLRequester->setURL( aDir );
}

///////////////////////////////////////////////////////////////////////////////

bool CheckoutDialog::pruneDirs() const
{
    return m_base->pruneDirsCheck->isChecked();
}

///////////////////////////////////////////////////////////////////////////////

TQString CheckoutDialog::tag() const
{
    return m_base->tagEdit->text();
}

///////////////////////////////////////////////////////////////////////////////

TQString CheckoutDialog::module() const
{
    return m_base->moduleEdit->text();
}

///////////////////////////////////////////////////////////////////////////////

void CheckoutDialog::slotFetchModulesList()
{
    setCursor( KCursor::waitCursor() );

    if (serverPath().isEmpty() || workDir().isEmpty())
        return;

    DCOPRef job = m_service->moduleList( serverPath() );
    if (!m_service->ok())
        return;

    m_job = new CvsJob_stub( job.app(), job.obj() );
    // We only need to know when it finishes and then will grab the output
    // by using m_job->output() :-)
    connectDCOPSignal( job.app(), job.obj(), "jobFinished(bool,int)", "slotJobExited(bool,int)", true );
    connectDCOPSignal( job.app(), job.obj(), "receivedStdout(TQString)", "receivedOutput(TQString)", true );

    kdDebug() << "Running: " << m_job->cvsCommand() << endl;
    m_job->execute();
}

///////////////////////////////////////////////////////////////////////////////

void CheckoutDialog::slotJobExited( bool /*normalExit*/, int /*exitStatus*/ )
{
    kdDebug(9006) << "CheckoutDialog::slotModulesListFetched() here!" << endl;

    kdDebug(9006) << "Received: " << m_job->output().join( "\n" ) << endl;

//    m_base->modulesListView->insertStringList( m_job->output() );
}

///////////////////////////////////////////////////////////////////////////////

void CheckoutDialog::slotReceivedOutput( TQString someOutput )
{
    kdDebug( 9006 ) << " Received output: " << someOutput << endl;

    setCursor( KCursor::arrowCursor() );

    // Fill the modules TDEListView if the list obtained is not empty
    // TQStringList modules = m_job->output();
    TQStringList modules = TQStringList::split( "\n", someOutput );
    if (modules.count() <= 0)
        return;

    TQStringList::iterator it = modules.begin();
    for ( ; it != modules.end(); ++it )
    {
        TQStringList l = TQStringList::split( " ", (*it) );
        // Now, l[0] is the module name, l[1] is ... another string ;-)
        new ModuleListViewItem( m_base->modulesListView, l[0], l[1] );
    }
}

void CheckoutDialog::slotReceivedErrors( TQString someErrors )
{
	kdDebug( 9006 ) << " Received errors: " << someErrors << endl;
}

///////////////////////////////////////////////////////////////////////////////

void CheckoutDialog::slotModuleSelected( TQListViewItem * )
{
	ModuleListViewItem *aModuleItem = static_cast<ModuleListViewItem*>(
		m_base->modulesListView->selectedItem()
	);
	if (!aModuleItem)
		return;

	m_base->moduleEdit->setText( aModuleItem->alias() );
}

///////////////////////////////////////////////////////////////////////////////

void CheckoutDialog::fetchUserCvsRepositories()
{
	TQStringList repositories;

	TQFile cvspass( TQDir::homeDirPath() + TQDir::separator() + ".cvspass" );
	if (!cvspass.open( IO_ReadOnly ))
		return;
	TQByteArray data = cvspass.readAll();
	cvspass.close();

	TQTextIStream istream( data );
	// Entries are like:
	// /1 :pserver:marios@cvs.kde.org:2401/home/kde Ahz:UIK?=d ?
	// /1 :pserver:mario@xamel:2401/home/cvsroot aJT_d'K?=d ?
	while (!istream.eof()) {
		TQString line = istream.readLine();
		TQStringList lineElements = TQStringList::split( " ", line );
		if (lineElements.count() > 1) {
			repositories << lineElements[ 1 ];
		}
	}

	fillServerPaths( repositories );
}

///////////////////////////////////////////////////////////////////////////////

void CheckoutDialog::slotOk()
{
	TQString errorMessage = TQString();

	if (!(workDir().length() > 0) && TQFile::exists( workDir() ))
		errorMessage = i18n( "Please, choose a valid working directory" );
	else if (!(serverPath().length() > 0))
		errorMessage = i18n( "Please, choose a CVS server." );
	else if (!(module().length() > 0))
		errorMessage = i18n( "Please, fill the CVS module field." );

	if (errorMessage.isNull())
		KDialogBase::slotOk();
	else
		KMessageBox::error( this, errorMessage );
}


#include "checkoutdialog.moc"
