//==============================================
//  copyright            : (C) 2003-2005 by Will Stokes
//==============================================
//  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.
//==============================================

//Systemwide includes
#include <qframe.h>
#include <qlabel.h>
#include <qradiobutton.h>
#include <qlineedit.h>
#include <qapplication.h>
#include <qdir.h>
#include <qbuttongroup.h>
#include <qcombobox.h>
#include <qpushbutton.h>
#include <qlayout.h>
#include <qlineedit.h>
#include <qspinbox.h>
#include <qfiledialog.h>

//Projectwide includes
#include "mosaicOptionsDialog.h"
#include "../../clickableLabel.h"
#include "../../window.h"
#include "../../titleWidget.h"
#include "../../statusWidget.h"
#include "../../../config.h"
#include "../../../configuration/configuration.h"
#include "../../../backend/album.h"
#include "../../../backend/tools/imageTools.h"
#include "../../../backend/manipulations/mosaic.h"

#define MAX_DEPTH 4
#define MAX_FILES 1000

#include <iostream>
using namespace std;

//==============================================
MosaicOptionsDialog::MosaicOptionsDialog( QWidget *parent ) : QDialog(parent,NULL,true)
{
  //--------------
  //Tile size options:
  QFrame* tileSizeOptions = new QFrame(this);
  
  QLabel* tileSizeLabel = new QLabel( tr("Tile size:"), this );
  tileSizes = new QComboBox( tileSizeOptions );
  tileSizes->insertItem( tr("Tiny") );
  tileSizes->insertItem( tr("Small") );
  tileSizes->insertItem( tr("Medium") );
  tileSizes->insertItem( tr("Large") );
  tileSizes->insertItem( tr("Huge") );
  tileSizes->insertItem( tr("Custom") );
  
  tileSizePreview = new QLabel( "(? x ?)", tileSizeOptions );
  tileWidth  = new QSpinBox( 1, 500, 1, tileSizeOptions );
  tileSizeX  = new QLabel( "x", tileSizeOptions );
  tileHeight = new QSpinBox( 1, 500, 1, tileSizeOptions );
  
  //set defaults
  tileWidth->setValue( 40 );
  tileHeight->setValue( 40 );
  
  //default to small
  tileSizes->setCurrentItem( 1 );
  updateTileSizePreview();
  
  //update custom controls when selection changes in the future
  connect( tileSizes, SIGNAL(activated(int)), this, SLOT(updateTileSizePreview()) );  
  
  QGridLayout* tileSizeGrid = new QGridLayout( tileSizeOptions, 1, 6, 0 );
  tileSizeGrid->addWidget( tileSizes,  1, 0 );
  tileSizeGrid->addWidget( tileSizePreview,  1, 1 );
  tileSizeGrid->addWidget( tileWidth,        1, 2 );
  tileSizeGrid->addWidget( tileSizeX,        1, 3 );
  tileSizeGrid->addWidget( tileHeight,       1, 4 );
  tileSizeGrid->setColStretch( 5, 1 );
  tileSizeGrid->setSpacing( WIDGET_SPACING );
  //--------------
  //Tile type options:
  QFrame* tileTypeOptions = new QFrame(this);
  
  QLabel* tileTypeLabel = new QLabel( tr("Base tiles on:"), this );
  //------------------------------
  tileType_albumPhotos = new QRadioButton( tr("Album photos"), tileTypeOptions );  
  tileType_albumPhotos->setChecked(true);
  //------------------------------  
  tileType_solidColors = new QRadioButton( tr("Solid colors"), tileTypeOptions );  
  //------------------------------  
  tileType_imagesFrom = new QRadioButton( tr("Images from:"), tileTypeOptions );  
  
  locationVal = new QLineEdit( tileTypeOptions );
  
  Configuration* config = ((Window*)qApp->mainWidget())->getConfig();
  QString path = config->getString( "loadSave", "addPhotoDir" );
  QDir testPath(path);
  if(!testPath.exists())
  {
    config->resetSetting( "loadSave", "addPhotoDir" );
    path = config->getString( "loadSave", "addPhotoDir" );
  }
  locationVal->setText( path );
  locationVal->setCursorPosition(0);
  
  browseButton = new ClickableLabel( tileTypeOptions );
  browseButton->setPixmap( QPixmap(QString(IMAGE_PATH)+"buttonIcons/browse.png") );
  connect( browseButton, SIGNAL(clicked()), SLOT(browse()) );  
  
  //in the future enable/disable the images from line edit and browse button when
  //the thrid option is selected/unselected. also force this to take place now as well
  connect( tileType_imagesFrom, SIGNAL(stateChanged(int)),
           this, SLOT(updateImagesFromOptions()) );
  updateImagesFromOptions();
  //------------------------------    
  
  QButtonGroup* typeGroup = new QButtonGroup( tileTypeOptions );
  typeGroup->hide();
  typeGroup->insert( tileType_albumPhotos );
  typeGroup->insert( tileType_solidColors );
  typeGroup->insert( tileType_imagesFrom );
 
  QGridLayout* tileTypeGrid = new QGridLayout( tileTypeOptions, 3, 3, 0 );
  tileTypeGrid->addMultiCellWidget( tileType_albumPhotos,   0,0, 0,2 );
  tileTypeGrid->addMultiCellWidget( tileType_solidColors,   1,1, 0,2 );
  tileTypeGrid->addWidget(          tileType_imagesFrom,   2,0 );
  tileTypeGrid->addWidget(          locationVal,  2,1 );
  tileTypeGrid->addWidget(          browseButton, 2,2 );
  
  tileTypeGrid->setColSpacing(1, 300);
  tileTypeGrid->setColStretch(1, 1);
  tileTypeGrid->setSpacing( WIDGET_SPACING );
  //--------------
  //Dialog buttons:  
  QFrame* buttonsFrame =   new QFrame( this, "dialogButtons" );
                                
  QPushButton* applyButton = new QPushButton( tr("Apply"), buttonsFrame );
  applyButton->setDefault(true);
  applyButton->setFocus();
  connect( applyButton, SIGNAL(clicked()), SLOT(accept()) );

  QPushButton* cancelButton = new QPushButton( tr("Cancel"), buttonsFrame );
  connect( cancelButton, SIGNAL(clicked()), SLOT(reject()) );
   
  QGridLayout* buttonsGrid = new QGridLayout( buttonsFrame, 1, 2, 0 );
  buttonsGrid->addWidget( applyButton,  0, 0 );
  buttonsGrid->addWidget( cancelButton, 0, 1 );
  buttonsGrid->setSpacing( WIDGET_SPACING );
  //--------------
  //Top level grid  
  QGridLayout* mainGrid = new QGridLayout( this, 5, 2, 0 );

  mainGrid->setRowStretch( 0, 1 );
  mainGrid->addWidget( tileSizeLabel,            1,0, Qt::AlignRight | Qt::AlignVCenter );
  mainGrid->addWidget( tileSizeOptions,          1,1 );
  mainGrid->addWidget( tileTypeLabel,            2,0, Qt::AlignRight | Qt::AlignVCenter );
  mainGrid->addWidget( tileTypeOptions,          2,1 );
  mainGrid->setRowStretch( 3, 1 );
  mainGrid->addMultiCellWidget( buttonsFrame,    4,4, 0,1, Qt::AlignHCenter );
  mainGrid->setSpacing( WIDGET_SPACING );
  mainGrid->setMargin( WIDGET_SPACING );  
  //--------------
  //Window caption
  setCaption( tr("Mosaic Options") );
  //-------------------------------
  //set window to not be resizeable
  this->show();
//  setFixedSize(size());
  //-------------------------------
}
//==============================================
MosaicOptions* MosaicOptionsDialog::getOptions()
{
  //construct a list of files based on the user selection
  QStringList files = determineFilesList();
  
  //get selected tile size
  QSize tileSize = determineTileSize();
  
  //return a populated mosaic options object
  return new MosaicOptions( files, tileSize, ((Window*)qApp->mainWidget())->getStatus() );
}
//==============================================
QSize MosaicOptionsDialog::determineTileSize()
{
  if( tileSizes->currentItem() == 0 )      return QSize(  20,  20 );
  else if( tileSizes->currentItem() == 1 ) return QSize(  40,  40 );
  else if( tileSizes->currentItem() == 2 ) return QSize(  65,  65 );
  else if( tileSizes->currentItem() == 3 ) return QSize( 100, 100 );
  else if( tileSizes->currentItem() == 4 ) return QSize( 150, 150 );
  else                                     return QSize( tileWidth->value(), tileHeight->value() );
}
//==============================================
QStringList MosaicOptionsDialog::determineFilesList()
{
  //Album photos
  if(  tileType_albumPhotos->isChecked() )
  {
    Album* albm = ((Window*)qApp->mainWidget())->getTitle()->getAlbum();
    return albm->getThumbnailFilenames();
  }
  
  //Solid colors - return empty list
  else if ( tileType_solidColors->isChecked() ) { return QStringList(); }
  //Images from...
  else
  {
     QStringList files;
     QString path = locationVal->text();
     appendImagesInPath( files, path, 0 );
     return files;
  }
}
//==============================================
void MosaicOptionsDialog::appendImagesInPath(QStringList& files, QString path, int depth)
{
//  cout << "appending files in " << path << "\n";
  QDir tmpDir;
  tmpDir.setPath( path );

  //add all iamges  
  tmpDir.setFilter( QDir::Files | QDir::Readable );
  tmpDir.setNameFilter( "*.gif;*.jpg;*.jpeg;*.png;*.xpm;*.GIF;*.JPG;*.JPEG;*.PNG;*.XPM" );  
  QStringList images = tmpDir.entryList();
  QStringList::iterator it;
  QSize imageRes;
  for(it = images.begin(); it != images.end(); it++ ) 
  {
    //check we can get a decent resolution out of the file
    getImageSize( tmpDir.absFilePath( *it ), imageRes );
    if( imageRes.width() <= 0 || imageRes.height() <= 0 ) continue;
    
//    cout << "appending " << *it << "\n";
    files.append( tmpDir.absFilePath( *it ) ); 
    
    //break out if we have too many files    
    if( files.count() >= MAX_FILES ) break;
  }    
  
  //recurse on all directories (but not symbolic links) - but only go down three levels
  if( depth < MAX_DEPTH && files.count() < MAX_FILES )
  {
    tmpDir.setFilter( QDir::Dirs | QDir::Readable | QDir::NoSymLinks );
    tmpDir.setNameFilter( "*" );
    QStringList directores = tmpDir.entryList();
    for(it = directores.begin(); it != directores.end(); it++ ) 
    {  
      QString dir = *it;
      if( dir.compare( "." ) == 0 || dir.compare( ".." ) == 0 ) continue;
      
      appendImagesInPath( files, tmpDir.absFilePath( *it ), depth+1 ); 
    }
  }
}
//==============================================
void MosaicOptionsDialog::updateTileSizePreview()
{
  //get selected tile size
  QSize tileSize = determineTileSize();

  //show/hide custom controls
  bool customSelected = tileSizes->currentItem() == tileSizes->count()-1;
  
  tileSizePreview->setShown( !customSelected );
  tileWidth->setShown ( customSelected );
  tileSizeX->setShown ( customSelected );
  tileHeight->setShown( customSelected );
  
  //update tile size preview text
  if( !customSelected )
  {
    tileSizePreview->setText( QString("(%1 x %2)").arg( tileSize.width() ).arg( tileSize.height() ) );
  }
  
  //update preview image
}
//==============================================
void MosaicOptionsDialog::updateImagesFromOptions()
{
  bool enabled = tileType_imagesFrom->isChecked();
  locationVal->setEnabled( enabled );
  browseButton->setEnabled( enabled );
}
//==============================================
void MosaicOptionsDialog::browse()
{
  //get directory from user
  QString dirName = QFileDialog::getExistingDirectory( locationVal->text(), this, NULL, tr("Images directory") );
  
  if(!dirName.isNull())
    locationVal->setText( dirName );
}
//==============================================



