/****************************************************************************
** listboxcolortext.h file.
**
**   Created :
**        by : Varol Okan
** Copyright : (c) Varol Okan
**   License : GPL v 2.0
**
** This file re-implements the QListBoxText class
** and adds only a background color to it.
**
** For later this could be enhanced to include a small Icon at the beginning
** Which indicates the type (I.e. single movie, movie collection, or dvd-slideshow).
**
** Another icon on the right side could indicate if a movie is already
** connected to a button or action.
**
** And yet another Icon could indicate the (intended) Format of the Movie.
**
*****************************************************************************/
#include <qfileinfo.h>
#include <qlistview.h>
#include <qpainter.h>
#include <qimage.h>
#include <qtimer.h>

#include "global.h"
#include "qdvdauthor.h"
#include "messagebox.h"
#include "sourcefileentry.h"
#include "listviewitemmedia.h"
#include "xml_slideshow.h"

ListViewItemMedia::ListViewItemMedia (QListView *pListView, SourceFileEntry *pEntry, const QColor &theColor)
	: QListViewItem (pListView, QString (), pEntry->qsDisplayName)
{
	initMe (pEntry, theColor);
}

ListViewItemMedia::ListViewItemMedia (QListViewItem *pListViewItem, SourceFileEntry *pEntry, const QColor &theColor)
	: QListViewItem (pListViewItem, QString (), pEntry->qsDisplayName)
{
	initMe (pEntry, theColor);
}

ListViewItemMedia::ListViewItemMedia (QListView *pListView, QListViewItem *pAfterItem, SourceFileEntry *pEntry, const QColor &theColor)
	: QListViewItem (pListView, pAfterItem, QString (), pEntry->qsDisplayName)
{
	initMe (pEntry, theColor);
}

ListViewItemMedia::ListViewItemMedia ( QListViewItem *pListViewItem, SourceFileInfo *pInfo, const QColor &color, QString str, QSize size )
  : QListViewItem ( pListViewItem, QString ( ), str )
{
  m_iButtonState     = StateStop;
  m_backgroundColor  = color;
  m_pSourceFileEntry = NULL;
  m_pSourceFileInfo  = pInfo;
  m_pAnimateMini     = NULL;
  m_sizeThumbnails   = size;
  m_pPixmap          = NULL;
}

ListViewItemMedia::~ListViewItemMedia ()
{
  if ( m_pAnimateMini )
    delete m_pAnimateMini;
  m_pAnimateMini = NULL;
  if ( m_pPixmap )
    delete m_pPixmap;
  m_pPixmap = NULL;
}

void ListViewItemMedia::initMe ( SourceFileEntry *pEntry, const QColor &theBaseColor )
{
  // Here we create the sub items according to the SourceFileEntry -> listFileInfos
  int t;
  QColor              theColor;
  QFileInfo           fileInfo;
  SourceFileInfo     *pInfo;
  m_backgroundColor  = theBaseColor;
  m_pSourceFileEntry = pEntry;
  m_pSourceFileInfo  = NULL;
  m_iButtonState     = StateStop;
  m_iPreviousButtonState = 1000;
  m_pAnimateMini     = NULL;
  m_pPixmap          = NULL;
  m_sizeThumbnails   = QSize ( 50, 50 );

  sortChildItems (-1, false);
  setOpen (true);
  setDragEnabled (true);
  setDropEnabled (true);

  if ( ! pEntry )
    return;

  m_sizeThumbnails = pEntry->sizeThumbnail;

  for(t=pEntry->listFileInfos.count()-1;t>=0;t--)	{
    pInfo = pEntry->listFileInfos[t];
    if ( ! pInfo )
      continue;
    if ( pInfo->pTranscodeInterface )
      theColor = QColor ( COLOR_MOVIE_TRANSCODE );
    else
      theColor = theBaseColor;
    fileInfo.setFile ( pInfo->qsFileName );

    QString qsInfo (fileInfo.fileName () + QString ("\n") + pInfo->qsLength);
    ListViewItemMedia *pItem = new ListViewItemMedia ( this, pInfo, theColor, qsInfo, m_sizeThumbnails );
    pItem->setOpen (true);
    pItem->setDragEnabled (true);
    pItem->setDropEnabled (true);
    if (pInfo->pPreview)	{
      QPixmap thePixmap;
      QImage scaledImage (pInfo->pPreview->smoothScale (pEntry->sizeThumbnail, QImage::ScaleMin));
      if (pEntry->bSoundSource)	// No buttons for a sound - SourceFileEntry ...
        thePixmap = QPixmap (scaledImage);
      else
        thePixmap = pItem->attachButtons (scaledImage, pEntry->sizeThumbnail);
      pItem->setPixmap (0, thePixmap);
    }
    pItem->setDragEnabled (true);
  }
}

void ListViewItemMedia::updateItem ()
{
  SourceFileInfo *pInfo = sourceFileInfo ( );
  if ( ! pInfo )
    return;

  m_backgroundColor   = QColor (COLOR_MOVIE_FILES_OK);
  if ( pInfo->qsStatus != QString ("Ok") )
    m_backgroundColor = QColor (COLOR_MOVIE_FILES_BAD);
  if ( pInfo->pTranscodeInterface )
    m_backgroundColor = QColor (COLOR_MOVIE_TRANSCODE);

  QFileInfo fileInfo ( pInfo->qsFileName );
  QString qsInfo ( fileInfo.fileName () + QString ("\n") + pInfo->qsLength );
  setText ( 1, qsInfo);
}

void ListViewItemMedia::replaceInfo (SourceFileInfo *pInfo)
{
  SourceFileEntry *pEntry = NULL;
  if (sourceFileInfo() == pInfo)	{
    pEntry = ((ListViewItemMedia *)parent())->sourceFileEntry();
    if (!pEntry)
      return;

    QImage scaledImage ( pInfo->pPreview->smoothScale (pEntry->sizeThumbnail, QImage::ScaleMin ) );
    QFileInfo fileInfo ( pInfo->qsFileName );
    QString   qsInfo   ( fileInfo.fileName () + QString ("\n") + pInfo->qsLength );
    setText (1, qsInfo);
    m_backgroundColor   = QColor (COLOR_MOVIE_FILES_OK);
    if (pInfo->qsStatus != QString ("Ok"))
      m_backgroundColor = QColor (COLOR_MOVIE_FILES_BAD);
    if ( pInfo->pTranscodeInterface )
      m_backgroundColor = QColor (COLOR_MOVIE_TRANSCODE);

    // attach the buttons and force a repaint of the buttons ...
    m_iPreviousButtonState = StateUndef;
    QPixmap thePixmap = attachButtons (scaledImage, pEntry->sizeThumbnail);
  }
  else if (sourceFileEntry ())	{
    pEntry = sourceFileEntry();
    ListViewItemMedia *pChild = (ListViewItemMedia *)firstChild ();
    while (pChild)	{
      pChild->replaceInfo (pInfo);
      pChild = (ListViewItemMedia *)pChild->nextSibling ();
    }
    // Here we check for the color of the header ... only if all status's are Ok do we give
    // the Ok color to the header too .
    m_backgroundColor     = QColor (COLOR_MOVIE_FILES_OK);
    for (uint t=0; t<pEntry->listFileInfos.count ();t++)	{
      if (pEntry->listFileInfos[t]->qsStatus != QString ("Ok"))	{
	m_backgroundColor = QColor (COLOR_MOVIE_FILES_BAD);
	break;
      }
    }
  }
}

void ListViewItemMedia::attachButtons ( QImage *pSourceImage, QPixmap *pTargetPix )
{
   QImage tempImage;
   tempImage  = pSourceImage->smoothScale ( m_sizeThumbnails, QImage::ScaleMin );
  *pTargetPix = attachButtons ( tempImage,  m_sizeThumbnails );
}

QPixmap &ListViewItemMedia::attachButtons ( QImage &theImage, QSize sizeThumbnail )
{
  static QPixmap thePixmap;
  // This function will attach the buttons to the left side of the image.
  // Play / Stop / Back
  int iThirdHeight = (int)( (float)sizeThumbnail.height ( ) / 3.0 );
  int iOffset = iThirdHeight;
  int iDeltaY = (int)( ( sizeThumbnail.height ( ) - theImage.height ( ) ) / 2.0 );
  if ( ( iDeltaY < 1 ) || ( iDeltaY > sizeThumbnail.height ( ) ) )
         iDeltaY = 0;
  // Here we create the final imageExtension (empty QImage)
  QImage finalImage ( sizeThumbnail.width ( ) + iOffset, sizeThumbnail.height ( ), theImage.depth ( ) );
  finalImage.fill ( 0 ); // fill all black 
  // Next we fill in the image
  bitBlt ( &finalImage, iOffset, iDeltaY, (const QImage *)&theImage, 0, 0, theImage.width(), theImage.height(), Qt::CopyROP);
  
  thePixmap.convertFromImage ( finalImage );
  // And then we draw the Buttons ...
  drawButtonState ( &thePixmap );
  return thePixmap;
}

void ListViewItemMedia::drawButtonState (QPixmap *pPixmap)
{
	if ( ! pPixmap )
		return;

	// This function will draw the buttons over the passed Pixmap
	uint t;
	bool bSelected;
	QPixmap theButton;
	QImage theImage;
	char arrayNormalButtonState [][20] = {"button_play.png",  "button_stop.png",  "button_back.png"};
	char arrayPressedButtonState[][20] = {"button_cplay.png", "button_cstop.png", "button_cback.png"};
	int iThirdHeight = (int)((float)pPixmap->height() / 3.0);
	int iOffset = iThirdHeight;

	for (t=0;t<3;t++)	{
		bSelected = false;
		if ((t == 0) && (m_iButtonState == StatePlay) )
			bSelected = true;
		else if ((t == 1) && (m_iButtonState == StateStop) )
			bSelected = true;
		else if ((t == 2) && (m_iButtonState == StateBack) )
			bSelected = true;

		if (bSelected)
			theImage = QImage().fromMimeSource(arrayPressedButtonState[t]).smoothScale (iOffset, iThirdHeight);
		else
			theImage = QImage().fromMimeSource(arrayNormalButtonState[t]).smoothScale(iOffset, iThirdHeight);
		theButton = theImage;
		bitBlt (pPixmap, 0, t*iThirdHeight, &theButton, 0, 0, theButton.width(), theButton.height(),  Qt::CopyROP);
	}
	setPixmap (0, *pPixmap);
	m_iPreviousButtonState = m_iButtonState;
}

void ListViewItemMedia::paintCell (QPainter *pPainter, const QColorGroup &cg, int iColumn, int iWidth, int iAlign)
{
	if ( ! pPainter )
		return;
	// FIXME:
	// Still some improvements to have the full width colored in  the m_backgroundColor
	QColorGroup theColors = cg;
	if (isSelected())	{
		theColors.setColor(QColorGroup::Base, theColors.highlight() );
		theColors.setColor(QColorGroup::Text, theColors.highlightedText() );
	}
	else
		theColors.setColor(QColorGroup::Base, m_backgroundColor);

	QListViewItem::paintCell (pPainter, theColors, iColumn, iWidth, iAlign);
//	pPainter->drawLine (0, 0, iWidth, 0);
	pPainter->drawLine (0, height()-1, iWidth, height()-1);
	// After we have drawn the full cell, we are going to draw the button states
	// If we have a SourceFileInfo - object

	if ( (iColumn == 0) && (sourceFileEntry() == NULL) )	{
		// Need to check if we have a SoundEntry.
		SourceFileEntry *pSourceFileEntry = ((ListViewItemMedia *)parent())->sourceFileEntry();
		if (pSourceFileEntry->bSoundSource)
			return;
		drawButtonState ((QPixmap *)pixmap(0));
	}
}

QColor ListViewItemMedia::backgroundColor ()
{
	return m_backgroundColor;

}

SourceFileEntry *ListViewItemMedia::sourceFileEntry ()
{
	return m_pSourceFileEntry;
}

SourceFileInfo *ListViewItemMedia::sourceFileInfo ()
{
	return m_pSourceFileInfo;
}

void ListViewItemMedia::itemClicked(QPoint &thePoint)
{
  // Okay if the header is clicked, we simply return ...
  if ( ! sourceFileInfo ( ) )
    return;
  SourceFileEntry  *pSourceFileEntry =  sourceFileEntry ( );
  if ( ! pSourceFileEntry )
       pSourceFileEntry = ( (ListViewItemMedia *)parent ( ) )->sourceFileEntry ( );
  if ( pSourceFileEntry->bSoundSource )
    return;
  // this function is called when the user clicks in the ListView.
  // Here we check if it hit one of the buttons ...
  QPoint   p = listView ( )->mapFromGlobal ( thePoint );
  QRect rect = listView ( )->itemRect ( this );
  int iStartWidth  = listView ( )->treeStepSize ( ) * 2;
  int iThirdHeight = (int)( (float)height ( ) / 3.0 );
  // Play /Stop / Back is th order
  if ( ( p.x ( ) > iStartWidth ) && 
       ( p.x ( ) < iStartWidth + iThirdHeight ) && 
       ( p.y ( ) < rect.y ( )  + rect.height ( ) ) )  {
    if ( p.y ( ) > rect.y ( ) )
      m_iButtonState = StatePlay;
    if ( p.y ( ) > rect.y ( ) + iThirdHeight )
      m_iButtonState = StateStop;
    if ( p.y ( ) > rect.y ( ) + iThirdHeight * 2.0 )
      m_iButtonState = StateBack;
  }
  // Next is to see what the user wants to do.
  CXmlSlideshow *pSlideshow = sourceFileInfo ( )->pSlideshow;
  if ( m_iButtonState != m_iPreviousButtonState )  {
    if ( pSlideshow )
      miniButton ( m_iButtonState, pSlideshow );
    else
      miniButton ( m_iButtonState, sourceFileInfo ( )->qsFileName );
  }

  if ( m_iButtonState == StateBack )
       m_iButtonState  = StateStop;

  drawButtonState ( (QPixmap *)pixmap ( 0 ) );
  listView ( )->triggerUpdate ( );
}

void ListViewItemMedia::miniButton ( int iState, QString &qsFileName )
{
  if ( ! m_pAnimateMini ) {
    Cache::Thumbs::Entry *pEntry = Global::pThumbsCache->find ( qsFileName );
    if ( pEntry ) {
      m_pAnimateMini = new AnimateMini ( this );
      m_pAnimateMini->initMe ( pEntry );
    }
    else // No cache object available yet ...
      return;
  }
  else
    m_pAnimateMini->refreshButtonState ( );

  if ( iState  == StateStop )
    m_pAnimateMini->stop  ( );
  else if ( iState == StatePlay )
    m_pAnimateMini->start ( );
  else if ( iState == StateBack )
    m_pAnimateMini->info  ( );
}

void ListViewItemMedia::miniButton ( int iState, CXmlSlideshow *pSlideshow )
{
  if ( ! m_pAnimateMini )  {
    if ( pSlideshow )  {
      m_pAnimateMini = new AnimateMini ( this );
      m_pAnimateMini->initMe ( pSlideshow );
    }
    else // No Slideshow ... etrange ...
      return;
  }
  else
    m_pAnimateMini->refreshButtonState ( );

  if ( iState  == StateStop )
    m_pAnimateMini->stop  ( );
  else if ( iState == StatePlay )
    m_pAnimateMini->start ( );
  else if ( iState == StateBack )
    m_pAnimateMini->info  ( );
}

void ListViewItemMedia::setProgress ( float fProgress )
{
  ListViewItemMedia *pItem;
  // Okay found the SourceFileInfo now we need the ListViewItemMedia - object for this Info.
  pItem = (ListViewItemMedia *)firstChild ( );
  while ( pItem )  {
    pItem->setProgress ( fProgress );
    pItem = (ListViewItemMedia *)pItem->nextSibling();
  }

  if ( m_pAnimateMini )
       m_pAnimateMini->setProgress ( fProgress );
  else if ( pixmap ( 0 ) )  {
       if ( ! m_pPixmap  )  // The first time around we'll have to create the temp pixmap
              m_pPixmap = new QPixmap ( *pixmap ( 0 ) );
       QPixmap thePixmap = *m_pPixmap;
       renderProgress  (   &thePixmap, fProgress );
       setPixmap       ( 0, thePixmap );
  }

  if ( ( fProgress == -1.0 ) && ( m_pPixmap ) )  {
    delete m_pPixmap;
    m_pPixmap = NULL;
  }
}

void ListViewItemMedia::renderProgress ( QPixmap *pPixmap, float fProgress )
{
  if ( ( ! pPixmap ) || ( fProgress == -1.0 ) )
    return;

  if ( fProgress > 100.0f )
       fProgress = 100.0f;
  if ( fProgress <   0.0f )
       fProgress =   0.0f;

  int iXOffset = (int)( (float)pPixmap->height ( ) / 3.0 ) + 5;
  int iYOffset = (int)(1.5 * iXOffset);

  QFont theFont ( "Courier", (int)(iXOffset / 2.0), QFont::Bold ); // iXOffset == FontSize was 12
  QString   qsProgress = QString ( "%1%" ).arg ( (int)fProgress );
  QPainter  thePainter ( pPixmap );
  thePainter.setPen    ( QColor ( 255, 255, 100 ) );
  thePainter.setBrush  ( Qt::Dense4Pattern );
  thePainter.setFont   ( theFont );
  thePainter.drawRect  ( iXOffset-5, 0, pPixmap->width ( )-iXOffset+5, pPixmap->height ( ) );
  thePainter.drawText  ( iXOffset, iYOffset, qsProgress );
}

void ListViewItemMedia::nextThumb ( )
{

}

AnimateMini::AnimateMini ( ListViewItemMedia *pItem )
{
  m_pItem          = pItem;
  m_arrayPix       = NULL;
  m_iCurrentPix    = 0;
  m_iNumberOfPix   = 0;
  m_fProgress      = -1.0f;
  m_pTimerThumbing = new QTimer ( this );
  connect ( m_pTimerThumbing, SIGNAL( timeout ( ) ), this, SLOT ( slotAnimate ( ) ) );
}

AnimateMini::~AnimateMini ( )
{
  stop  ( );
  clear ( );
  delete m_pTimerThumbing;
}

void AnimateMini::slotAnimate ( )
{
  if ( m_arrayPix ) {
    m_iCurrentPix ++;
    if ( m_iCurrentPix >= m_iNumberOfPix )
         m_iCurrentPix  = 0;
    if ( m_fProgress == -1.0 )
         m_pItem->setPixmap ( 0, *m_arrayPix[m_iCurrentPix] );
    else
         m_pItem->setProgress ( m_fProgress );
  }
}

void AnimateMini::setProgress ( float fProgress )
{
  m_fProgress = fProgress;
  QPixmap thePixmap = *m_arrayPix[m_iCurrentPix];
  m_pItem->renderProgress ( &thePixmap, fProgress );
  m_pItem->setPixmap      ( 0, thePixmap );
//printf ( "AnimateMini::setProgress <%f>\n", fProgress );
}

void AnimateMini::reset ( )
{
  m_iCurrentPix = 0;
  m_pItem->setPixmap ( 0, m_pixmapOrig );
}

void AnimateMini::clear ( )
{
  int t;
  if ( m_arrayPix ) {
    for ( t=0; t<m_iNumberOfPix; t++ )
      delete m_arrayPix[t];
    delete []m_arrayPix;
  }
}

void AnimateMini::initMe ( Cache::Thumbs::Entry *pCache )
{
  uint t;
  QImage tempImage;
  const QPixmap *pPixmap = m_pItem->pixmap ( 0 );
  if ( pPixmap )
    m_pixmapOrig = *pPixmap;
  else {
    QImage error = QImage::fromMimeSource ( "error.jpg" );
    error = error.smoothScale     ( 45,45 );
    m_pixmapOrig.convertFromImage ( error );
    pPixmap = &m_pixmapOrig;
  }

  stop  ( );
  clear ( );

  if ( ! pCache->arrayOfThumbs )
         pCache->loadImages  ( );

  m_iNumberOfPix = pCache->iNumberOfThumbs;
  m_arrayPix = new QPixmap *[m_iNumberOfPix];
  for ( t=0; t<(uint)m_iNumberOfPix; t++ ) {
     m_arrayPix[t] = new QPixmap;
     m_pItem->attachButtons ( pCache->arrayOfThumbs[t], m_arrayPix[t] );
  }
}

void AnimateMini::initMe ( CXmlSlideshow *pSlideshow )
{
  uint t, iMaxNrImages, iImgNr;
  QImage tempImage;
  CXmlSlideshow::img_struct *pXmlImage;
  const QPixmap *pPixmap = m_pItem->pixmap ( 0 );

  if ( pPixmap )
    m_pixmapOrig = *pPixmap;
  else {
    QImage error = QImage::fromMimeSource ( "error.jpg" );
    error = error.smoothScale     ( 45,45 );
    m_pixmapOrig.convertFromImage ( error );
    pPixmap = &m_pixmapOrig;
  }

  stop  ( );
  clear ( );

  if ( pSlideshow )  {
    iMaxNrImages = pSlideshow->countImg ( );
    m_iNumberOfPix = ( iMaxNrImages < 10 ) ? iMaxNrImages : 10;
    m_arrayPix = new QPixmap *[m_iNumberOfPix];
    for ( t=0; t<(uint)m_iNumberOfPix; t++ ) {
       m_arrayPix[t] = new QPixmap;
       iImgNr = (uint)( (float)iMaxNrImages / (float)m_iNumberOfPix * (float)t );
       pXmlImage = pSlideshow->getImg ( iImgNr );
       if ( pXmlImage )
         tempImage.load ( pXmlImage->src );
       else
         tempImage = QImage::fromMimeSource ( "error.jpg" );
       tempImage = tempImage.smoothScale ( 45, 45, QImage::ScaleMin );
       m_pItem->attachButtons ( &tempImage, m_arrayPix[t] );
    }
  }
}

void AnimateMini::refreshButtonState ( )
{
  int t;
  for ( t=0; t<m_iNumberOfPix; t++ )
    m_pItem->drawButtonState ( m_arrayPix[t] );
}

void AnimateMini::start ( )
{
  if ( ! m_pTimerThumbing->isActive ( ) )
         m_pTimerThumbing->start ( 1500 );
}

void AnimateMini::stop ( )
{
  if ( m_pTimerThumbing->isActive ( ) )
       m_pTimerThumbing->stop     ( );
  reset ( );
}

//#include "render_client.h"
void AnimateMini::info ( )
{
  if ( m_pTimerThumbing->isActive ( ) )
       m_pTimerThumbing->stop     ( );

  SourceFileInfo *pInfo = m_pItem->sourceFileInfo ( );
  if ( ! pInfo ) {
    SourceFileEntry *pEntry =  m_pItem->sourceFileEntry ( );
    if ( ( ! pEntry )  || ( pEntry->listFileInfos.count ( ) < 1 ) )
      return;

    pInfo = pEntry->listFileInfos[0];
  }

  // Check if the SourceFileEntry is in the process of being rendered ...
  SourceFileEntry *pEntry =  m_pItem->sourceFileEntry ( );
  if ( ! pEntry )  {
    ListViewItemMedia *pParent = (ListViewItemMedia *)m_pItem->parent ( );
    if ( pParent && pParent->sourceFileEntry ( ) )
      pEntry = pParent->sourceFileEntry ( );
    else 
      pEntry = Global::pApp->sourceFileEntry ( 0 );
  }
  if ( pEntry && pEntry->bIsSlideshow )
    return;
//    bool bRet = Render::Manager::registerEntry ( pEntry );
//printf ( "AnimateMini::info registerEntry <%p> <%s>\n", pEntry, bRet ? "true" : "false" );
//    return;

  Global::pApp->editSourceFileInfo ( pInfo );
}



