/****************************************************************************
** Derived off of DialogButtonTrans
**
**   Created : Sun June 12 09:13:25 2009
**        by : Varol Okan, using Kat
** Copyright : (c) Varol Okan
**   License : GPL v 2.0
**
**
****************************************************************************/

#include <qdir.h>
#include <qtimer.h>
#include <qlabel.h>
#include <qcursor.h>
#include <qlayout.h>
#include <qspinbox.h>
#include <qpainter.h>
#include <qcheckbox.h>
#include <qfileinfo.h>
#include <qlineedit.h>
#include <qtabwidget.h>
#include <qmessagebox.h>
#include <qpushbutton.h>
#include <qprogressbar.h>
#include <qapplication.h>

#include "global.h"
#include "qdvdauthor.h"
#include "buttonobject.h"
#include "filepreviewdialog.h"
#include "dialogbuttontrans.h"

static const char * xpmNoCheck[] = {
"16 16 17 1",
"       c None",
".      c #110807",
"+      c #3A0D0F",
"@      c #B00000",
"#      c #A3080B",
"$      c #CD0000",
"%      c #C20407",
"&      c #E40A0B",
"*      c #862829",
"=      c #5C3440",
"-      c #C41A1E",
";      c #E51E21",
">      c #C4373A",
",      c #EA3037",
"'      c #AA545A",
")      c #E85B60",
"!      c #E99398",
"  >>)     -)'   ",
"  *!>     >!*.  ",
" +'!)@   @)!'+. ",
"=')))>@ #>)))'=.",
"=',,,,->-,,,,>==",
".+#&$$;);$$&#+. ",
" .+@%@@%@@%@+.  ",
"  .*-@@@@@-*+   ",
"   #>-####>#    ",
"  #@@@@@@@@@#   ",
" #-%@%$;$%@%-#  ",
">-%%$$&,&&$%%-> ",
")-$$&&&$&&&$$%>>",
"@%&&&&$ $&&&&%@ ",
" %;);&   $&;&%  ",
"  ;),     &,,   "};

static const char * xpmCheck[] = {
"16 16 17 1",
"       c None",
".      c #041504",
"+      c #024D01",
"@      c #3C5039",
"#      c #197313",
"$      c #148F0E",
"%      c #3C9237",
"&      c #32B229",
"*      c #53AA4B",
"=      c #7DB474",
"-      c #4AD53E",
";      c #78C570",
">      c #61D256",
",      c #A0CF9C",
"'      c #8EDF86",
")      c #6AF253",
"!      c #77F26C",
"                ",
"            ++  ",
"           $%%# ",
"          $*=%#+",
"         #*=*$#+",
"  %%#   $*;*$$#@",
" %,,%. $*;>&$#. ",
"#=,,;$$*'>-&#.  ",
"#*;'';;'>-&#.   ",
"##$>'''>)-$+    ",
" +#&-!!)-&#     ",
"  #$&))!&&      ",
"   $$>>>&       ",
"    &$*>        ",
"     )          ",
"                "};

DialogButtonTrans::Item::Item ( QIconView *pIconView, const QString &qsText, const QPixmap &thePix, bool bChecked )
  : QIconViewItem ( pIconView )
{
  m_bChecked   = bChecked;
  m_pixmap     = thePix;
  m_qsFileName = qsText;
  refreshIcon ( );
}

QString DialogButtonTrans::Item::fileName ( )
{
  return m_qsFileName;
}

void DialogButtonTrans::Item::setChecked ( bool bChecked )
{
  if ( bChecked == m_bChecked )
    return;

  m_bChecked = bChecked;
  QPoint position = pos ( );
  refreshIcon   ( );
  move ( position );
  iconView ( )->updateContents ( );
}

bool DialogButtonTrans::Item::toggle ( )
{
  setChecked ( !m_bChecked );
  return m_bChecked;
}

bool DialogButtonTrans::Item::isChecked ( )
{
  return m_bChecked;
}

void DialogButtonTrans::Item::calcRect ( const QString &string )
{
  QIconViewItem::calcRect ( string );
  QRect rect  ( 0, 0, 0, 0 );
  setTextRect ( rect );
  setItemRect ( pixmapRect ( ) );
}

void DialogButtonTrans::Item::refreshIcon ( )
{
  QPixmap pixCheck, thePix;
  int iX, iY, iWidth, iHeight;
  QColor clrBlue ( 120, 120, 255 );

  if ( m_bChecked )
    pixCheck = QPixmap ( xpmCheck   );
  else
    pixCheck = QPixmap ( xpmNoCheck );

  iX = iY = 1;
  iWidth  = m_pixmap.width  ( );
  iHeight = m_pixmap.height ( );

  int  iSize = iWidth;
  if ( iSize < iHeight )
       iSize = iHeight;
  if ( iSize < 16 )
       iSize = 16;
  thePix = QPixmap ( iSize + 2, iSize + 2 + 16);
  thePix.fill ( 0xFFFFFF );

  iX = (int)( ( iSize - iWidth  ) / 2.0 ) + 1;
  iY = (int)( ( iSize - iHeight ) / 2.0 ) + 1;

  copyBlt ( &thePix, iX, iY, &m_pixmap );

  // Frame the pix
  iWidth  += 2;
  iHeight += 2;
  QPainter thePainter ( &thePix );
  thePainter.setPen   ( clrBlue );
  thePainter.drawLine (       0,       0, iSize-1,       0 );
  thePainter.drawLine ( iSize-1,       0, iSize-1, iSize-1 );
  thePainter.drawLine ( iSize-1, iSize-1,       0, iSize-1 );
  thePainter.drawLine (       0, iSize-1,       0,       0 );

  // next we copy the check box
  iX = (int)( ( (float)iWidth - 16.0 ) / 2.0 );
  copyBlt ( &thePix, iX, iSize + 1, &pixCheck, 0, 0, 16, 16 );

  setPixmap ( thePix );
}

DialogButtonTrans::DialogButtonTrans ( ButtonTransition *pTransition, QWidget *pParent )
  : uiDialogButtonTrans ( pParent )
{
  m_pTransition = new ButtonTransition;
  if ( pTransition )
    *m_pTransition = *pTransition;

  initMe ( false );
}

DialogButtonTrans::DialogButtonTrans ( ButtonTransition *pTransition, QStringList &list, QWidget *pParent )
  : uiDialogButtonTrans ( pParent )
{
  m_pTransition = new ButtonTransition;
  if ( pTransition )
    *m_pTransition = *pTransition;
  initEnabled ( list );
  initMe      ( true );
}

DialogButtonTrans::~DialogButtonTrans ( )
{
  if ( m_pTransition )
    delete m_pTransition;
  m_pTransition = NULL;

  if ( m_pTimer )
    delete m_pTimer;
  m_pTimer = NULL;

  for ( int t=0; t<THUMBNAIL_COUNT; t++ )  {
    delete m_arrayPix[t];
    m_arrayPix[t] = NULL;
  }
}

void DialogButtonTrans::initMe ( bool bMultiMode )
{
  m_pTimer      =  NULL;
  m_iThumbSize  =    80;
  m_iCurrentPix =     0;
  m_bAnimated   = false;
  m_bMultiMode  = bMultiMode;

  if ( bMultiMode )  {
    m_pButtonNoTransition->setText ( tr ( "&No Transitions" ) ); // plural in case wecome from the DVDMenu
    QWidget *pTab = m_pTabWidget->page ( 0 );
    while  ( pTab ) {
      delete pTab;
      pTab = m_pTabWidget->page ( 0 );
    }

    connect ( m_pButtonSelectAll, SIGNAL ( clicked ( ) ), this, SLOT ( slotSelectAll ( ) ) );
    connect ( m_pButtonClearAll,  SIGNAL ( clicked ( ) ), this, SLOT ( slotClearAll  ( ) ) );
  }
  else  {
    m_pButtonSelectAll->hide ( );
    m_pButtonClearAll->hide  ( );
    m_pFrameUserDefined->setEnabled ( m_pTransition->bUserFile );
    if ( m_pTransition->bUserFile )
         m_pEditUserFile->setText ( m_pTransition->qsTransitionVideoFileName );
    connect ( m_pButtonBrowse,     SIGNAL ( clicked ( ) ), this, SLOT ( slotBrowse      ( ) ) );
    connect ( m_pCheckUserDefined, SIGNAL ( clicked ( ) ), this, SLOT ( slotUserDefined ( ) ) );
  }

  for ( int t=0; t<THUMBNAIL_COUNT; t++ )
    m_arrayPix[t] = new QPixmap;

  m_pSpinFilterDelay->setValue ( (int)m_pTransition->fDuration );
  QString qsLabel = m_pTransition->qsTransitionName;

  setLabel ( qsLabel ); //m_pTransition->qsTransitionName );

  // build all library tabs.
  int      t;
  QDir     theDir;
  QString  qsPrefixDir, qsDirName;
  QStringList listDirs, listFiles;

  qsPrefixDir = QString ("%1/share/qdvdauthor/slideshow/transitions").arg ( Global::qsSystemPath );
  if ( !  theDir.exists ( qsPrefixDir ) )
    return;

  theDir.cd ( qsPrefixDir, TRUE );
  listDirs = theDir.entryList ( QDir::Dirs, QDir::Name );
  if ( listDirs.count ( ) < 3 ) // 3 = this dir / parent dir / background file
    return;

  // The following widgets will create th progress dialog on the fly.
  QDialog       progressDialog  ( NULL );
  QGridLayout  *pProgressLayout = new QGridLayout  ( &progressDialog );
  QProgressBar *pProgressBar    = new QProgressBar ( &progressDialog );
  pProgressLayout->addWidget( pProgressBar, 0, 0 );
  progressDialog.resize( QSize(537, 50).expandedTo ( progressDialog.minimumSizeHint ( ) ) );
  progressDialog.show  ( );

  for ( t=0; t<(int)listDirs.count ( ); t++ )  {
    // Here we go through all directories 
    qsDirName = listDirs[t];
    if ( ( qsDirName == ".") || ( qsDirName == "..") )
      continue;

    progressDialog.setCaption ( tr ( "Creating preview for buttons : %1" ).arg ( listDirs[t] ) );

    // Next we need to get the file list of the found directory
    QString qsPath = qsPrefixDir + "/" + qsDirName;
    theDir.cd ( qsPath );
    listFiles = theDir.entryList ( QDir::Files, QDir::Name );
    createTab ( qsDirName, qsPath, listFiles );

    pProgressBar->setProgress ( (int)((float)t / listDirs.count ( ) * 100.0) );
    qApp->processEvents ( 100 ); // do some event processing ...
  }

  connect ( m_pButtonNoTransition, SIGNAL ( clicked ( ) ), this, SLOT ( slotNoTransition ( ) ) );
  connect ( m_pButtonAnim,         SIGNAL ( clicked ( ) ), this, SLOT ( slotAnim         ( ) ) );

  QTimer::singleShot ( 200, this, SLOT ( slotAfterInit ( ) ) );
}

void DialogButtonTrans::initEnabled ( QStringList &list )
{
  m_listEnabled = list;
//  QStringList::iterator it = m_listEnabled.begin ( );
//  while ( it != m_listEnabled.end ( ) )  {
//    printf ( "In List<%s>\n", (*it++).ascii() );
//  }
}

void DialogButtonTrans::setLabel ( QString qsTransition )
{
  QString qsLabel;
  if ( m_bMultiMode )
    qsLabel = QString ( "<p align=\"center\"><b>Random Transitions</b></p>" );
  else  {
    QFileInfo fileInfo ( qsTransition );
    qsLabel = QString ( "<p align=\"center\"><b>%1</b></p>" ).arg ( fileInfo.fileName ( ) );
  }
  m_pLabelName->setText ( qsLabel );
}

void DialogButtonTrans::createTab ( QString qsDirName, QString qsPath, QStringList &listFiles )
{
  int t;
  bool bChecked;
  if ( listFiles.count ( ) < 1 )
    return;

  // Okay, ready to create the tab ... 
  QFileInfo fileInfo;
  QString qsFileName, qsFile;
  QSize grid ( 80, 80 );
  QWidget       *pTab      = new QWidget     ( m_pTabWidget, "pTab" );
  QGridLayout   *pLayout   = new QGridLayout ( pTab, 1, 1, 4, 2, "pLayout" );
  QIconView     *pIconView = new QIconView   ( pTab, "pIconViewLibrary" );
  QIconViewItem *pItem     = NULL;
  m_listViews.append ( pIconView );

  pLayout->addWidget         ( pIconView,  0, 0 );
  pIconView->setAutoArrange  ( true  );
  pIconView->setShowToolTips ( true );
  m_pTabWidget->insertTab    ( pTab,  qsDirName, 0 );

  for ( t=0; t<(int)listFiles.count ( ); t++ ) {
    if ( listFiles[t] == "crossfade.png" )
      continue;
    qsFileName = qsPath + "/" + listFiles[t];
    QPixmap thePix;
    QImage  theImage ( qsFileName );

    if ( theImage.isNull ( ) )
      continue;

    if ( ( theImage.width ( ) > m_iThumbSize ) || ( theImage.height ( ) > m_iThumbSize ) )
      theImage = theImage.smoothScale ( m_iThumbSize, m_iThumbSize, QImage::ScaleMin );

    thePix.convertFromImage ( theImage );
    fileInfo.setFile ( listFiles[t] );
    qsFile   = fileInfo.baseName  ( );
    bChecked = isChecked   ( qsFile );

    pItem = new Item ( pIconView, listFiles[t], thePix, bChecked );
    pItem->setKey ( qsFileName );
  }

  pIconView->setSelectionMode ( QIconView::NoSelection );
  pIconView->setAutoArrange   (  TRUE );
  pIconView->setItemsMovable  ( FALSE );
  pIconView->setResizeMode    ( QIconView::Adjust );
  pIconView->sort ( );
  pIconView->arrangeItemsInGrid ( grid, TRUE );

  connect ( pIconView, SIGNAL ( mouseButtonClicked ( int, QIconViewItem *, const QPoint & ) ), this, SLOT ( slotClicked ( int, QIconViewItem *, const QPoint & ) ) );
}

bool DialogButtonTrans::isChecked ( QString &qsString )
{
  QStringList::iterator it = m_listEnabled.begin ( );
  while ( it != m_listEnabled.end ( ) )  {
    if ( *it++ == qsString )
      return true;
  }

  return false;
}

void DialogButtonTrans::slotAfterInit ( )
{
  // Somehow the first IconView does not arrange in a grid.
  // so we have to force it to arrange
  if ( m_listViews.count ( ) < 1 )
    return;

  const QPoint pos;
  m_listViews[0]->sort ( true );

  int  iTabCounter = 0;
  Item      *pItem = NULL;
  QIconView *pView = NULL;
  QValueList<QIconView *>::iterator it = m_listViews.begin ( );
  while ( it != m_listViews.end ( ) )  {
    pView = *it++;

    pItem = (Item *)pView->firstItem ( );
    while ( pItem )  {
      if  ( pItem->key ( ) == m_pTransition->qsTransitionName )  {
        m_pTabWidget->setCurrentPage ( iTabCounter );
        slotClicked   ( Qt::LeftButton, pItem, pos );
        pView->ensureItemVisible ( pItem );
        return;
      }
      pItem = (Item *)pItem->nextItem ( );
    }
    iTabCounter ++;
  }

  slotClicked ( Qt::LeftButton, m_listViews[0]->firstItem ( ), pos );
}

ButtonTransition *DialogButtonTrans::getTransition ( )
{
  return m_pTransition;
}

void DialogButtonTrans::slotClicked ( int iButton, QIconViewItem *pItm, const QPoint & )
{
  if ( ! pItm )
    return;

  if ( iButton != Qt::LeftButton )
    return;

  Item *pItem = NULL;
  if ( ! m_bMultiMode )  {
    QValueList<QIconView *>::iterator it = m_listViews.begin ( );
    while ( it !=m_listViews.end ( ) )  {
      QIconView *pIconView = *it++; //pItm->iconView ( );
      if ( ! pIconView )
        continue;

      pItem = (Item *)pIconView->firstItem ( );
      while ( pItem )  {
        pItem->setChecked ( pItem == pItm );
        pItem = (Item *)pItem->nextItem ( );
      }
    }
  }
  else  { // ( m_bMultiMode )  {
    pItem = (Item *)pItm;
    pItem->toggle ( );
  }

  pItem = (Item *)pItm;
  QImage theImage ( pItem->key ( ) );
  if ( theImage.isNull ( ) )
    return;

  m_qsTransitionName = pItem->key ( );
  // Stop the animation if currently ongoing.
  if ( m_bAnimated )
    slotAnim ( );

  setLabel ( pItem->key ( ) );
  theImage = theImage.smoothScale ( m_pLabelPreview->size ( ) );
  QPixmap thePix;
  thePix.convertFromImage ( theImage );
  m_pLabelPreview->setPaletteBackgroundPixmap ( thePix );
}

void DialogButtonTrans::slotUserDefined  ( )
{
  m_pFrameUserDefined->setEnabled ( m_pCheckUserDefined->isChecked ( ) );
}

void DialogButtonTrans::slotBrowse ( )
{
  QString qsVideoFilter = Global::pApp->getMovieFilter ( );
  QString qsFilter      = QString ( "Videos ( " ) + qsVideoFilter + QString (" );;All ( * )" );
  QString qsVideoName   = FilePreviewDialog::getOpenFileName ( NULL, Global::qsCurrentPath, qsFilter, this, tr ( "Select video" ), tr ( "Select a video." ) );
  if ( qsVideoName.isNull ( ) )
    return;

  QFileInfo fileInfo  ( qsVideoName );
  Global::qsCurrentPath = fileInfo.dirPath ( TRUE );

  m_pEditUserFile->setText ( qsVideoName );
}

void DialogButtonTrans::slotSelectAll ( )
{
  if ( m_bMultiMode )  {
    Item *pItem = NULL;
    QValueList<QIconView *>::iterator it = m_listViews.begin ( );
    while ( it !=m_listViews.end ( ) )  {
      QIconView *pIconView = *it++; //pItm->iconView ( );
      if ( ! pIconView )
        continue;

      pItem = (Item *)pIconView->firstItem ( );
      while ( pItem )  {
        pItem->setChecked ( true );
        pItem = (Item *)pItem->nextItem ( );
      }
    }
  }
}

void DialogButtonTrans::slotClearAll ( )
{
  if ( m_bMultiMode )  {
    Item *pItem = NULL;
    QValueList<QIconView *>::iterator it = m_listViews.begin ( );
    while ( it !=m_listViews.end ( ) )  {
      QIconView *pIconView = *it++; //pItm->iconView ( );
      if ( ! pIconView )
        continue;

      pItem = (Item *)pIconView->firstItem ( );
      while ( pItem )  {
        pItem->setChecked ( false );
        pItem = (Item *)pItem->nextItem ( );
      }
    }
  }
}

void DialogButtonTrans::slotAnim ( )
{
  // User pushed button [Anim]
  QString qsAnim = tr ( "A\nn\ni\nm" );
  QString qsStop = tr ( "S\nt\no\np" );
  if ( m_bAnimated )  {
    m_pButtonAnim->setText  ( qsAnim );
    if ( m_pTimer )
         m_pTimer->stop ( );
    m_bAnimated = false;
  }
  else  {
    m_pButtonAnim->setText ( qsStop );
    // First we init the timer if required
    if ( ! m_pTimer )  {
      m_pTimer = new QTimer ( this );
      connect ( m_pTimer, SIGNAL ( timeout ( ) ), this, SLOT ( slotAnimPix ( ) ) );
    }
    // start the timer
    m_pTimer->start ( 100 );
    m_bAnimated = true;
  }
  // and lastly, we recreate the pixmaps / preview ...
  recreatePix ( );
}

void DialogButtonTrans::slotAnimPix ( )
{
  m_iCurrentPix ++;
  if ( m_iCurrentPix < 0 )
    return;

  if ( m_iCurrentPix >= THUMBNAIL_COUNT )  {
    m_iCurrentPix = -10; // 1 sec pause between each run ...
    return;
  }
  if ( m_arrayPix[m_iCurrentPix]->isNull ( ) )
    return;
  m_pLabelPreview->setPaletteBackgroundPixmap ( *m_arrayPix[m_iCurrentPix] );
}

void DialogButtonTrans::recreatePix ( )
{
  Utils theUtils;
  QCursor myCursor     ( QCursor::WaitCursor );
  QApplication::setOverrideCursor ( myCursor );

  QPixmap *pPixmap = (QPixmap *)m_pLabelPreview->paletteBackgroundPixmap ( );
  if ( ! pPixmap )
    return;
  QPixmap filterPix = *pPixmap;

  if ( m_bAnimated )  {
    int      t, iDiff = 0;
    float    fDelta;
    QPixmap *array[THUMBNAIL_COUNT];

    for ( t=0; t<THUMBNAIL_COUNT; t++ )
      array[t] = new QPixmap ( m_pLabelPreview->size ( ) );

    QImage filter = filterPix.convertToImage ( ); //( qsFilterName );
    QImage start  = QImage::fromMimeSource ( "default.jpg" ).copy ( );
    QImage stop   = QImage::fromMimeSource (  "splash.jpg" ).copy ( );
    QImage result     ( start ); // init the size
    QImage background ( m_pLabelPreview->size ( ), 32 );
    background.fill   ( 0x000000 );

    filter = filter.smoothScale ( m_pLabelPreview->size ( ) );
    start  = start.smoothScale  ( m_pLabelPreview->size ( ) );
    stop   = stop.smoothScale   ( m_pLabelPreview->size ( ) );
    fDelta = 512.0f / ( THUMBNAIL_COUNT - iDiff - 1 );

    for ( t=0; t<THUMBNAIL_COUNT; t++ )  {
      theUtils.augmentAlpha ( (int)( fDelta * t ), filter, start, stop, result );
      array[t]->convertFromImage ( result );
    }

    for ( t=0; t<THUMBNAIL_COUNT; t++ )  {
      if ( m_arrayPix[t] )
        delete m_arrayPix[t];
      m_arrayPix[t] = array[t];
    }
  }
  m_iCurrentPix = 0;

  QApplication::restoreOverrideCursor ( );
}

QStringList &DialogButtonTrans::getEnabledList ( )
{
  return m_listEnabled;
}

void DialogButtonTrans::accept ( )
{
  if ( m_bMultiMode )  {
    int   iCount = 0;
    Item *pItem  = NULL;
    QString   qsName;
    QFileInfo fileInfo;
    m_listEnabled.clear ( );

    QValueList<QIconView *>::iterator it = m_listViews.begin ( );
    while ( it !=m_listViews.end ( ) )  {
      QIconView *pIconView = *it++; //pItm->iconView ( );
      if ( ! pIconView )
        continue;

      pItem = (Item *)pIconView->firstItem ( );
      while ( pItem )  {
        if  ( pItem->isChecked ( ) )  {
          fileInfo.setFile     ( pItem->fileName ( ) );
          qsName = fileInfo.baseName  ( );
          m_listEnabled.append ( qsName );
          iCount ++;
        }
        pItem   = (Item *)pItem->nextItem ( );
      }
    }
    if ( iCount == 0 )  {
      QMessageBox::warning ( NULL, tr ( "Warning" ), tr ( "Please select at least one Transition." ), QMessageBox::Ok, QMessageBox::NoButton );
      return;
    }
  }

  if ( m_pTransition )  {
       m_pTransition->fDuration        = (float)m_pSpinFilterDelay->value ( );
       m_pTransition->bUserFile        = false;
       m_pTransition->iTransitionType  = 1; // AlphaTrans
       m_pTransition->qsTransitionName = m_qsTransitionName;
       if ( ! m_bMultiMode && m_pCheckUserDefined->isChecked ( ) && ! m_pEditUserFile->text ( ).isEmpty ( ) )  {
         m_pTransition->bUserFile      = true;
         m_pTransition->qsTransitionVideoFileName = m_pEditUserFile->text ( );
       }
  }
  uiDialogButtonTrans::accept ( );
}

void DialogButtonTrans::slotNoTransition ( )
{
  if ( m_pTransition )
    delete m_pTransition;
  m_pTransition   = NULL;
  m_listEnabled.clear( );

  uiDialogButtonTrans::accept ( );
}

