/****************************************************************************
** dialogselect.cpp
**
**   Created : Sat Nov 10 2007
**        by : Varol Okan using Kate
** Copyright : (c) Varol Okan
**   License : GPL v 2.0
**
*****************************************************************************/

#include <qapplication.h>
#include <qpushbutton.h>
#include <qvaluelist.h>
#include <qfileinfo.h>
#include <qcombobox.h>
#include <qlistview.h>
#include <qcheckbox.h>
#include <qlistbox.h>
#include <qheader.h>
#include <qtimer.h>

#include "sourcefileentry.h"
#include "messagebox.h"
#include "dialogselect.h"
#include "qdvdauthor.h"
#include "dvdmenu.h"
#include "global.h"

DialogSelect::DialogSelect ( QWidget *parent, const char *name, bool modal, WFlags fl )
  : uiDialogSelect ( parent, name, modal, fl )
{
  m_bShowAll = true;
  m_pListSelected->setSorting ( -1 );
  m_pListSelected->setSelectionMode  ( QListView::Single  );
  m_pListAvailable->setSelectionMode ( QListBox::Extended );

  connect ( m_pButtonUp,        SIGNAL ( clicked ( ) ), this, SLOT ( slotButtonUp        ( ) ) );
  connect ( m_pButtonDown,      SIGNAL ( clicked ( ) ), this, SLOT ( slotButtonDown      ( ) ) );
  connect ( m_pButtonAdd,       SIGNAL ( clicked ( ) ), this, SLOT ( slotButtonAdd       ( ) ) );
  connect ( m_pButtonRemove,    SIGNAL ( clicked ( ) ), this, SLOT ( slotButtonRemove    ( ) ) );
  connect ( m_pButtonAddAll,    SIGNAL ( clicked ( ) ), this, SLOT ( slotButtonAddAll    ( ) ) );
  connect ( m_pButtonRemoveAll, SIGNAL ( clicked ( ) ), this, SLOT ( slotButtonRemoveAll ( ) ) );
  connect ( m_pButtonShowAll,   SIGNAL ( clicked ( ) ), this, SLOT ( slotButtonShowAll   ( ) ) );
  connect ( m_pCheckLoop,       SIGNAL ( toggled ( bool ) ),     this, SLOT ( slotCheckLoop ( bool ) ) );
  connect ( m_pListAvailable,   SIGNAL ( selectionChanged ( ) ), this, SLOT ( slotSelectionChanged ( ) ) );

  QHeader *pHeader = m_pListSelected->header ( );
  if ( pHeader )
       connect ( pHeader, SIGNAL ( clicked ( int ) ), this, SLOT ( slotHeaderClicked ( int ) ) );
}

DialogSelect::~DialogSelect ( )
{
  uint t;
  for ( t=0; t<m_listSourceObjects.count ( ); t++ )
    delete m_listSourceObjects[t];
}

bool DialogSelect::initMe ( QStringList &list, bool bLoop )
{
  QDVDAuthor *pQDVDAuthor  = Global::pApp;
  QValueList<DVDMenu *>listMenus = pQDVDAuthor->getSubMenus ( );
  DVDMenu    *pCurrentMenu = pQDVDAuthor->getCurrentSubMenu ( );
  uint t, i,  iNrOfEntries = pQDVDAuthor->sourceFileCount   ( );
  SourceFileEntry  *pEntry = NULL;
  SourceFileInfo   *pInfo  = NULL;
  QStringList listFinalDestination;
  QString     qsEntry;

  //  QValueList<SourceFileEntry *> listEntries = pCurrentMenu->getSourceFileEntries( );
  QValueList<SourceFileInfo *> listFileInfos = pCurrentMenu->getSourceFileInfos  ( );
  m_qsCurrentMenuName = pCurrentMenu->name ( );

  listFinalDestination.append     ( "-- None --" );
  listFinalDestination.append     ( pQDVDAuthor->getVMGMenu ( )->getInterface ( )->qsMenuName );
  for ( t=0; t<listMenus.count    ( ); t++ )
    listFinalDestination.append   ( listMenus[t]->getInterface ( )->qsMenuName );
  m_pComboFinal->insertStringList ( listFinalDestination );
  m_pComboFinal->setEnabled       ( ! bLoop );
  m_pCheckLoop->setChecked        (   bLoop );

  // populate the list of all source files
  for ( t=0; t<iNrOfEntries; t++ ) {
    pEntry = pQDVDAuthor->sourceFileEntry ( t );
    if ( pEntry->bSoundSource )
      continue;
    for ( i=0; i<pEntry->listFileInfos.count ( ); i++ ) {
      ObjectEntry *pObjectEntry = new ObjectEntry;
      pObjectEntry->qsDisplayName = pEntry->qsDisplayName;
      pInfo = pEntry->listFileInfos[i];
      if ( pInfo ) {
	pObjectEntry->qsFileName    = pInfo->qsFileName;
	pObjectEntry->listChapters  = pInfo->listChapters;
	if ( pObjectEntry->listChapters.count ( ) < 1 )
	  pObjectEntry->listChapters.append ( "00:00:00.000" );
      }
      m_listSourceObjects.append ( pObjectEntry );
    }
  }

  if ( m_listSourceObjects.count ( ) < 1 ) {
    MessageBox::warning ( this, tr ( "Nothing to select from." ), tr ( "There are no video sources in the project.\n" ), QMessageBox::Ok, QMessageBox::NoButton );
    return false;
  }

  for ( t=0; t<listFileInfos.count ( ); t++ )
    m_listDVDMenuSourceFiles.append ( listFileInfos[t]->qsFileName );

  populateList ( );

  // After we have all in place we look at what we have gotten from the associated button
  initButton ( list );

  return true;
}

void DialogSelect::initButton ( QStringList &list )
{
  // entries in the list should look like this :
  // jump+-+<SourceFileEntry-DisplayName>+-+FileName+-+chapter
  int t, i;
  QStringList listEntry;
  QString qsEntryName, qsFileName, qsChapter, qsFinal;

  // first we check if the last entry in the list is a call to a Menu.
  qsFinal = list.last ( );
  listEntry = QStringList::split  ( STRING_SEPARATOR, qsFinal );
  if ( listEntry.count ( ) == 2 )
    m_pComboFinal->setCurrentText ( listEntry[1] );

  // Now for this to work we nee to have m_pListAvailable populated
  for ( t=list.count ( )-1; t>=0; t-- ) {
    listEntry = QStringList::split  ( STRING_SEPARATOR, list[t] );
    if ( listEntry.count ( ) == 4 ) {
      qsEntryName = listEntry[1];
      qsFileName  = listEntry[2];
      qsChapter   = listEntry[3];
      for ( i=0; i<(int)m_pListAvailable->count ( ); i++ ) {
	if ( m_pListAvailable->text ( i ) == qsFileName ) {
	  new QListViewItem ( m_pListSelected, qsFileName, qsChapter );
	  m_pListAvailable->removeItem ( i );
	  break; // leave the inner loop.
	}
      }
    }
  }
}

void DialogSelect::slotCheckLoop ( bool bChecked )
{
  m_pComboFinal->setEnabled ( !bChecked );
}

void DialogSelect::slotSelectionChanged ( )
{
  QTimer::singleShot ( 1, this, SLOT ( slotChangeChapters ( ) ) );
}

void DialogSelect::slotChangeChapters ( )
{
  QString qsFile = m_pListAvailable->currentText ( );
  if ( qsFile.isEmpty ( ) )
    return;
  QFileInfo fileInfo;
  uint t;

  for ( t=0; t<m_listSourceObjects.count ( ); t++ ) {
    fileInfo.setFile ( m_listSourceObjects[t]->qsFileName );
    if ( fileInfo.fileName ( ) == qsFile ) {
      m_pComboChapters->clear ( );
      m_pComboChapters->insertStringList( m_listSourceObjects[t]->listChapters );
	  if ( m_pComboChapters->count  ( ) > 0 )
           m_pComboChapters->setCurrentItem ( 0 );
      return;
    }
  }
}

void DialogSelect::slotButtonUp ( )
{
  QListViewItem *pItem = m_pListSelected->currentItem ( );
  if ( ! pItem )
    return;
  QListViewItem *pPrevItem = pItem->itemAbove ( );
  if ( ! pPrevItem )
    return;
  pPrevItem = pPrevItem->itemAbove ( );

  m_pListSelected->setSortColumn ( -1 );
  if ( ! pPrevItem ) {
    m_pListSelected->takeItem    ( pItem );
    m_pListSelected->insertItem  ( pItem );
    m_pListSelected->setSelected ( pItem, TRUE );
    return;
  }
  pItem->moveItem ( pPrevItem );
}

void DialogSelect::slotButtonDown ( )
{
  QListViewItem *pItem = m_pListSelected->currentItem ( );
  if ( ! pItem )
    return;
  QListViewItem *pNextItem = pItem->itemBelow ( );
  if ( ! pNextItem )
    return;
  m_pListSelected->setSortColumn ( -1 );
  pItem->moveItem ( pNextItem );
}

void DialogSelect::slotButtonAdd ( )
{
  QListBoxItem *pNextInLine  = NULL;
  QListBoxItem *pCurrentItem = NULL;
  QListBoxItem *pItem        = m_pListAvailable->firstItem ( );
  QValueList<QListBoxItem *> list;
  while ( pItem )  {
     if ( pItem->isSelected ( ) )
          list.append   ( pItem );
    pItem = pItem->next ( );
  }
  if ( list.size ( ) < 1 )
    return;

  // This is so we can select the next in line ...
  pNextInLine = list.last ( );
  if ( pNextInLine ) {
    pNextInLine = pNextInLine->next ( );
    if ( ! pNextInLine )
      pNextInLine = list.last ( ) ->prev ( );
    if ( pNextInLine )
       m_pListAvailable->setSelected ( pNextInLine, true );
  }

  QString qsChapter = m_pComboChapters->currentText ( );
  pCurrentItem = m_pListAvailable->item ( m_pListAvailable->currentItem ( ) );

  // only the first selected item gets the selected chapter.
  for ( int t=list.count ( )-1; t>=0; t-- ) {
    pItem = list[t];
    if ( pItem ) {
      if ( pItem == pCurrentItem )
	new QListViewItem ( m_pListSelected, pItem->text ( ), qsChapter );
      else
	new QListViewItem ( m_pListSelected, pItem->text ( ), QString ( "00:00:00.000" ) );
      delete pItem;
    }
  }
}

void DialogSelect::slotButtonRemove ( )
{
  QListViewItem *pItem = m_pListSelected->currentItem ( );
  if ( ! pItem )
    return;
  QString qsCurrent    = pItem->text ( 0 );
  if ( qsCurrent.isEmpty ( ) )
    return;
  
  m_pListSelected->removeItem  ( m_pListSelected->currentItem ( ) );
  m_pListAvailable->insertItem ( qsCurrent );
}

void DialogSelect::slotButtonAddAll ( )
{
  int t;

  if ( m_bShowAll )
    m_pButtonShowAll->setText ( tr ( "All Available Videos" ) );
  else
    m_pButtonShowAll->setText ( tr ( "All of %1" ).arg ( m_qsCurrentMenuName ) );

  for ( t=(int)m_pListAvailable->count ( )-1; t>=0; t-- )
    new QListViewItem ( m_pListSelected, m_pListAvailable->text ( t ), "00:00:00.000" );
  m_pListAvailable->clear ( );
}

void DialogSelect::slotButtonRemoveAll ( )
{
  m_pListSelected->clear ( );
  populateList ( );
}

void DialogSelect::slotButtonShowAll ( )
{
  // switches between displaying all available vide sources or only the ones of the current subMenu.
  m_bShowAll = ! m_bShowAll;
  populateList ( );
}

void DialogSelect::slotHeaderClicked ( int iColumn )
{
  m_pListSelected->setSortColumn ( iColumn );
}

void DialogSelect::populateList ( )
{
  uint      t;
  QFileInfo fileInfo;
  bool      bFound;
  QListViewItem *pItem;

  // switches between displaying all available vide sources or only the ones of the current subMenu.
  m_pListAvailable->clear ( );
  if ( m_bShowAll ) {
    m_pButtonShowAll->setText ( tr ( "All Available Videos" ) );
    for ( t=0; t<m_listSourceObjects.count ( ); t++ ) {
      fileInfo.setFile ( m_listSourceObjects[t]->qsFileName );
      bFound = false;
      pItem = m_pListSelected->firstChild ( );
      while ( pItem ) {
	if  ( pItem->text ( 0 ) == fileInfo.fileName ( ) ) {
	  bFound = true;
	  break; // exit inner loop
	}
	pItem = pItem->nextSibling ( );
      }
      if ( ! bFound )
	m_pListAvailable->insertItem ( fileInfo.fileName ( ) );
    } // end for - loop
  }
  else {
    m_pButtonShowAll->setText ( tr ( "All of %1" ).arg ( m_qsCurrentMenuName ) );
    for ( t=0; t<m_listDVDMenuSourceFiles.count ( ); t++ ) {
      fileInfo.setFile ( m_listDVDMenuSourceFiles[t] );
      bFound = false;
      pItem = m_pListSelected->firstChild ( );
      while ( pItem ) {
	if  ( pItem->text ( 0 ) == fileInfo.fileName ( ) ) {
	  bFound = true;
	  break; // exit inner loop
	}
	pItem = pItem->nextSibling ( );
      }
      if ( ! bFound )
	m_pListAvailable->insertItem ( fileInfo.fileName ( ) );
    } // end for - loop
  }
}

bool DialogSelect::getLoop ( )
{
  return m_pCheckLoop->isChecked ( );
}

QString DialogSelect::getFinalDestination ( )
{
  return m_pComboFinal->currentText ( );
}

QStringList DialogSelect::getSelected ( )
{
  uint           t;
  QString        qsItem;
  QFileInfo      fileInfo;
  QStringList    listReturn;
  QListViewItem *pItem;
  ObjectEntry   *pSourceObject;

  pItem = m_pListSelected->firstChild ( );
  while ( pItem ) {
    for ( t=0; t<m_listSourceObjects.count ( ); t++ ) {
      pSourceObject = m_listSourceObjects[t];
      fileInfo.setFile ( pSourceObject->qsFileName );
      if ( fileInfo.fileName ( ) == pItem->text ( 0 ) ) {
	qsItem  = QString ( "jump%1" ).arg ( STRING_SEPARATOR );
	qsItem += QString ( "%1%2"   ).arg ( pSourceObject->qsDisplayName ).arg ( STRING_SEPARATOR );
	qsItem += pItem->text ( 0 ) + STRING_SEPARATOR;
	qsItem += pItem->text ( 1 );
	listReturn.append( qsItem );
      }
    }
    pItem = pItem->nextSibling ( );
  }

  return listReturn;
}
