/***************************************************************************
                          transferwindow.cpp -  description
                             -------------------
    begin                : Wed Nov 3 2004
    copyright            : (C) 2004 by Diederik van der Boor
    email                : vdboor --at-- codingdomain.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 "transferwindow.h"

#include "../utils/kmessconfig.h"
#include "../kmessdebug.h"
#include "transferentry.h"

#include <KWindowSystem>



// Initialize the entries counter
int             TransferWindow::currentEntryID_(-1);
// Initialize the instance to zero
TransferWindow* TransferWindow::onlyInstance_(0);



// Constructor
TransferWindow::TransferWindow( QWidget *parent )
  : KMainWindow( parent )
  , Ui::TransferWindow()
{
  // Set up the interface and the window
  setObjectName( "Transfer" );
  QWidget *mainWidget = new QWidget( this );
  setupUi( mainWidget );
  setCentralWidget( mainWidget );

  // Do not steal focus from other windows when popping up
  setAttribute( Qt::WA_ShowWithoutActivating );

  // Get the scroll area's layout and add a flexible space to it, so our entries will stay at the top
  layout_ = static_cast<QVBoxLayout*>( transfersArea_->layout() );
  layout_->addStretch();

  // Set up the window
  setCaption( i18n("File Transfers") );
  applyMainWindowSettings( KMessConfig::instance()->getGlobalConfig( "TransferWindow" ) );

  // Set up the Clean Up and close button
  closeButton_->setFocus();
  closeButton_  ->setIcon( KIcon( "dialog-close" ) );
  cleanupButton_->setIcon( KIcon( "trash-empty"  ) );
  connect( cleanupButton_, SIGNAL( clicked() ), this, SLOT( cleanUp() ) );
  connect(   closeButton_, SIGNAL( clicked() ), this, SLOT(    hide() ) );

  // Set up the Download and Upload buttons
  downloadButton_->setIcon( KIcon( "go-down" ) );
  uploadButton_  ->setIcon( KIcon( "go-up"   ) );
  connect( downloadButton_, SIGNAL( toggled( bool ) ), this, SLOT( slotDownloadButtonToggled( bool ) ) );
  connect(   uploadButton_, SIGNAL( toggled( bool ) ), this, SLOT(   slotUploadButtonToggled( bool ) ) );

}



// Destructor
TransferWindow::~TransferWindow()
{
  if( ! onlyInstance_ )
  {
    // The singleton has already been destroyed
    return;
  }

#ifdef KMESSDEBUG_TRANSFERWINDOW
  kDebug() << "DESTROYED.";
#endif

  // Save the window size and position
  KConfigGroup group = KMessConfig::instance()->getGlobalConfig( "TransferWindow" );
  saveMainWindowSettings( group );

  // Destroy the instance data
  entryList_.clear();
  onlyInstance_ = 0;
}



// Add an entry to the transfer manager
int TransferWindow::addEntry( const QString filename, ulong filesize, bool incoming, const QImage preview )
{
#ifdef KMESSDEBUG_TRANSFERWINDOW
  kDebug() << "adding entry for '" << filename << "'.";
#endif

  // Create a new entry
  TransferEntry *entry = new TransferEntry( transfersArea_, filename, filesize, incoming, preview );

  // Add it to the transfers list
  entryList_[ ++currentEntryID_ ] = entry;
  entry->setTransferID( currentEntryID_ );

  // Connect the dialog so that if the user closes it, it's deleted.
  connect( entry, SIGNAL( cancelTransfer(int) ) ,
           this,  SIGNAL( cancelTransfer(int) ) );

#ifdef KMESSDEBUG_TRANSFERWINDOW
  kDebug() << "Adding entry to layout, showing it.";
#endif

  // Add it to the list of entries
  layout_->insertWidget( 0, entry );

  // Show the window
  show();
  KWindowSystem::demandAttention( winId() );

  return currentEntryID_;
}



// Mark a transfer as failed
void TransferWindow::failTransfer( int transferID, const QString &message )
{
  if( ! entryList_.contains( transferID ) )
  {
    return;
  }

  entryList_[ transferID ]->failTransfer( message );
}



// Mark a transfer as complete
void TransferWindow::finishTransfer( int transferID )
{
  if( ! entryList_.contains( transferID ) )
  {
    return;
  }

  entryList_[ transferID ]->finishTransfer();
}



// Set the status message of a transfer
void TransferWindow::setStatusMessage( int transferID, const QString &message )
{
  if( ! entryList_.contains( transferID ) )
  {
    return;
  }

  entryList_[ transferID ]->setStatusMessage( message );
}



// Update the progress bar of a transfer
void TransferWindow::updateProgress( int transferID, ulong bytesTransferred )
{
  if( ! entryList_.contains( transferID ) )
  {
    return;
  }

  entryList_[ transferID ]->updateProgress( bytesTransferred );
}



// Return an instance of the singleton. It's not named instance() due to the base class having an instance() method itself.
TransferWindow *TransferWindow::getInstance()
{
  if(onlyInstance_ == 0)
  {
    onlyInstance_ = new TransferWindow();
  }
  return onlyInstance_;
}



// Destroy the singleton.
void TransferWindow::destroy()
{
  delete onlyInstance_;
  onlyInstance_ = 0;
}



// The "Clean up" button was pressed
void TransferWindow::cleanUp()
{
#ifdef KMESSDEBUG_TRANSFERWINDOW
  kDebug() << "Cleaning up";
#endif

  int id;
  TransferEntry *entry;
  QMapIterator<int,TransferEntry*> it( entryList_ );

  // Clean up the list of transfers
  while( it.hasNext() )
  {
    it.next();

    // Copy the data before deleting, to avoid crashes
    id = it.key();
    entry = it.value();

    // Remove the entry only if it's an ended transfer and we don't need it anymore
    if( entry->isDone() )
    {
      // Delete the entry from the GUI and our list
      entryList_.remove( id );

#ifdef KMESSDEBUG_TRANSFERWINDOW
      kDebug() << "Removed " << entry->getFileName();
#endif

      delete entry;
    }
  }

  // Issue an update to the UI, just to be sure
  update();
}



// The "Download" button was pressed
void TransferWindow::slotDownloadButtonToggled( bool checked )
{
  if( checked )
  {
    // Show the download entries
    showEntries( true, true );
  }
  else
  {
    if( uploadButton_->isChecked() )
    {
      // Hide the download entries
      showEntries( true, false );
    }
    else
    {
      // Don't permit to user to deselect both buttons
      downloadButton_->setChecked( true );
    }
  }
}



// The "Upload" button was pressed
void TransferWindow::slotUploadButtonToggled( bool checked )
{
  if( checked )
  {
    // Show the upload entries
    showEntries( false, true );
  }
  else
  {
    if( downloadButton_->isChecked() )
    {
      // Hide the download entries
      showEntries( false, false );
    }
    else
    {
      // Don't permit to user to deselect both buttons
      uploadButton_->setChecked( true );
    }
  }
}



// Show or hide selected entries
void TransferWindow::showEntries( bool incoming, bool show )
{
  TransferEntry *entry;
  QMapIterator<int,TransferEntry*> it( entryList_ );

  // Search the selected entries
  while( it.hasNext() )
  {
    it.next();
    entry = it.value();

    // Check if the current entry is one of selected
    if( entry->isIncoming() == incoming )
    {
      // Show or hide the entry
      entry->setVisible( show );
    }
  }

  // Update to the UI
  update();
}


#include "transferwindow.moc"
