/***************************************************************************
    begin                : Tue Oct 16 19:03:20 EEST 2001
    copyright            : (C) 2001, 2006 by Mantia Andras
    email                : amantia@kdewebdev.org
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

/*Own include files*/
#include "kallery.h"
#include "kalleryfunctions.h"
#include "kalleryglobals.h"
#include "firstpage.h"
#include "selectsourcepage.h"
#include "thumbssourcepage.h"
#include "imagethumbpage.h"
#include "targetpath.h"
#include "descsourcepage.h"
#include "imageoptionspage.h"
#include "htmloptionspage.h"
#include "imagehtmlpage.h"
#include "lastpage.h"

/*Utility includes*/
#include <magick/api.h>

/*KDE header files*/
#include <kapplication.h>
#include <kcmdlineargs.h>
#include <kdebug.h>
#include <kfiledialog.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kpushbutton.h>
#include <kstandarddirs.h>

/*QT header files*/
#include <qeventloop.h>
#include <qprogressdialog.h>
#include <qregexp.h>

Kallery::Kallery(QWidget *parent, const char *name) : KWizard(parent, name, false)
{
  
  
  kdDebug() << "Kallery is starting up." << endl;

  QString appBaseDir = KGlobal::dirs()->findResourceDir("data","kallery/images/kallery.png")+"kallery/";
  kdDebug() << "Kallery data dir is: " << appBaseDir << endl;

  if (appBaseDir == "kallery/")
  {
    KMessageBox::information(this,i18n("The base data directory [$KDEDIR/share/apps/kallery] seems to be invalid, so the generation may fail.\n")+
                            i18n("You may need to do a \"make install\".\n"),i18n("Warning"));
  }

  KalleryGlobals::ref()->setBaseDir(appBaseDir);
  

  // set text of buttons again, so our translation will be used
  // available by extract and merge messages
  nextButton()->setText(i18n("&Next"));

  //KalleryFunctions::ref() contains the non GUI releated tasks (except the progress bar)
  KalleryFunctions::ref(this);

  KCmdLineArgs* args = KCmdLineArgs::parsedArgs();
  KalleryGlobals::ref()->options.printToStdOut = args->isSet("verbose");
  setCaption(i18n("Kallery wizard"));

  addFirstPage();
  addSelectSourcesPage();
  addThumbSourcePage();
  addImageThumbPage();
  addTargetPathPage();
  addDescSourcePage();
  addImageOptionsPage();
  addHtmlOptionsPage();
  addImageHtmlPage();
  addLastPage();

  kdDebug() << "All pages were added" << endl;

  connect(this,SIGNAL(selected(const QString &)),this,SLOT(slotPageHasChanged( const QString &)));
  connect(this,SIGNAL(helpClicked()),this,SLOT(slotShowHelp()));


  KalleryGlobals::ref()->setDefaultOptions();
 
  initFilters();
}

Kallery::~Kallery()
{
  delete KalleryFunctions::ref();
}

void Kallery::addFirstPage()
{
  FirstPage *firstPage = new FirstPage(this);

  setNextEnabled(firstPage, true);
  setHelpEnabled(firstPage, true);
  addPage(firstPage, i18n("STEP 1: Getting started..."));
  connect(firstPage, SIGNAL(projectLoaded()), SLOT(slotProjectLoaded()));
}

void Kallery::addSelectSourcesPage()
{
  SelectSourcePage *selectSourcePage = new SelectSourcePage(this);
  addPage(selectSourcePage, i18n("STEP 2: Select the sources..."));
  setNextEnabled(selectSourcePage, true);
}

void Kallery::addTargetPathPage()
{
  TargetPath *targetPathPage = new TargetPath(this);

  addPage(targetPathPage,i18n("STEP 5: Where to put the gallery files?"));
  setNextEnabled(targetPathPage,true);
}

void Kallery::addImageThumbPage()
{
  ImageThumbPage *imageThumbPage = new ImageThumbPage(this);

  addPage(imageThumbPage, i18n("STEP 4: Match image and thumbnail files...")) ;
  setNextEnabled(imageThumbPage, true);
}

void Kallery::addLastPage()
{
  LastPage *lastPage = new LastPage(this);

  addPage(lastPage,i18n("STEP 10: Final step, review the options.")) ;
  setBackEnabled(lastPage,true);
  setFinishEnabled(lastPage,true);
}

void Kallery::addThumbSourcePage()
{
  ThumbsSourcePage *thumbSourcePage = new ThumbsSourcePage(this);
  addPage(thumbSourcePage,i18n("STEP 3: Thumbnails..."));
  setNextEnabled(thumbSourcePage, true);
}

void Kallery::addDescSourcePage()
{
  DescSourcePage *descSourcePage = new DescSourcePage(this);
  addPage(descSourcePage, i18n("STEP 6: Describe the images..."));
  setNextEnabled(descSourcePage, true);
}

void Kallery::addHtmlOptionsPage()
{
  HtmlOptionsPage *htmlOptionsPage = new HtmlOptionsPage(this);

  addPage(htmlOptionsPage,i18n("STEP 8: Gallery look & feel..."));
  setNextEnabled(htmlOptionsPage,true);
}

void Kallery::addImageOptionsPage()
{
  ImageOptionsPage *imageOptionsPage = new ImageOptionsPage(this);

  addPage(imageOptionsPage,i18n("STEP 7: Image options..."));
  setNextEnabled(imageOptionsPage,true);
}

void Kallery::addImageHtmlPage()
{
  ImageHtmlPage *imageHtmlPage = new ImageHtmlPage(this);

  addPage(imageHtmlPage,i18n("STEP 9: Fullsize image look & feel."));
  setNextEnabled(imageHtmlPage,true);
}

void Kallery::initFilters()
{
  InitializeMagick(QDir::currentDirPath());

  const MagickInfo **mInfoList;
  unsigned long numberOfItems;

#ifdef IMAGEMAGICK_6_0
  mInfoList = GetMagickInfoList("*", &numberOfItems);
#else
  ExceptionInfo exception;
  GetExceptionInfo(&exception);
  mInfoList = GetMagickInfoList("*", &numberOfItems, &exception);
#endif

  QString tmpStr;
  QString allFilter;
  QString imageFilter;
  for (uint i = 0; i < numberOfItems; i++)
  {
    const MagickInfo *mInfo = mInfoList[i];
    tmpStr = mInfo->name;
    if (!tmpStr.isEmpty())
    {
      allFilter += "*."+  tmpStr.lower()+" ";
      imageFilter +=  "*." + tmpStr.lower() +"|"+ QString(mInfo->description)+
                                  " file (*."+ tmpStr.lower() +")\n";
    }
  };
  imageFilter = allFilter +"|All ImageMagick suported image files\n*|All files\n" + imageFilter;

  imageFilter.replace(QRegExp("/"),"");
  KalleryGlobals::ref()->setImageFilter(imageFilter);
  kdDebug() << "ImageMagick initalized, filters read." << endl;
}

void Kallery::next()
{
  bool goToNextPage;

  goToNextPage = true;

  WizardPageBase *currentP = dynamic_cast<WizardPageBase*>(currentPage());
  if (currentP)
    goToNextPage = currentP->processPage();

  QWidget *current = currentPage();

  if (goToNextPage)
  {
    /*Skip the thumbnail and image matching page if there were no thumbnails selected */
    if (current->isA("ThumbsSourcePage"))
      setAppropriate(page(indexOf(current) + 1), KalleryGlobals::ref()->options.thumbSetting == OptionType::LoadThumbnails );
    KWizard::next();
  }
}

void Kallery::accept()
{
  if (KalleryGlobals::ref()->options.relativePaths)
  {
    QString CSSDir;
    if (!KalleryGlobals::ref()->options.imageCSSFile.isEmpty())
    {
      CSSDir = QFileInfo(KalleryGlobals::ref()->options.imageCSSFile).dirPath();
      if (KalleryFunctions::ref()->makeRelativePath(KalleryGlobals::ref()->options.imageDestDir,CSSDir))
      {
        KalleryGlobals::ref()->options.imageCSSFile = CSSDir + QFileInfo(KalleryGlobals::ref()->options.imageCSSFile).fileName();
      }
    }
    if (!KalleryGlobals::ref()->options.galleryCSSFile.isEmpty())
    {
      CSSDir = QFileInfo(KalleryGlobals::ref()->options.galleryCSSFile).dirPath();
      if (KalleryFunctions::ref()->makeRelativePath(KalleryGlobals::ref()->projectBaseDir(),CSSDir))
      {
        KalleryGlobals::ref()->options.galleryCSSFile = CSSDir + QFileInfo(KalleryGlobals::ref()->options.galleryCSSFile).fileName();
      }
    }
    KalleryFunctions::ref()->makeRelativePath(KalleryGlobals::ref()->projectBaseDir(),KalleryGlobals::ref()->options.thumbDestDir);
    KalleryFunctions::ref()->makeRelativePath(KalleryGlobals::ref()->projectBaseDir(),KalleryGlobals::ref()->options.imageDestDir);
    if (KalleryGlobals::ref()->options.thumbSetting == OptionType::LoadThumbnails)
    {
      QString thumbDir;
      for (uint i = 0; i < KalleryGlobals::ref()->options.thumbList.count(); i++)
      {
        thumbDir = QFileInfo(KalleryGlobals::ref()->options.thumbList[i]).dirPath();
        KalleryFunctions::ref()->makeRelativePath(KalleryGlobals::ref()->projectBaseDir(),thumbDir);
        KalleryGlobals::ref()->options.thumbList[i] = thumbDir + QFileInfo(KalleryGlobals::ref()->options.thumbList[i]).fileName();
      }
    }
  }

  if (KalleryGlobals::ref()->options.thumbSetting == OptionType::GenerateThumbnails)
  {
    KalleryGlobals::ref()->options.thumbList.clear();
    for (uint i = 0; i < KalleryGlobals::ref()->options.imageList.count(); i++)
    {
      KalleryGlobals::ref()->options.thumbList.append(KalleryGlobals::ref()->options.thumbDestDir+QFileInfo(KalleryGlobals::ref()->options.imageList[i]).baseName()+"."+KalleryGlobals::ref()->options.thumbFormat);
    }
  }

  bool projectSaved = false;
  bool ok = false;
  while (!ok)
  {
    bool retry = false;
    QString projectFileName = KalleryGlobals::ref()->projectFile();
    if (projectFileName.isEmpty())
    {
      if (KMessageBox::questionYesNo(this,i18n("Do you want to save the project?"), i18n("Save project")) == KMessageBox::Yes)
      {
        projectFileName = KFileDialog::getSaveFileName(QFileInfo(KalleryGlobals::ref()->options.fileName).dirPath(),"*.kallery\n*|All files",this,i18n("Save project"));
        if (QFileInfo(projectFileName).exists())
        {
          if (KMessageBox::questionYesNo(this, i18n("<qt>The file <b>%1</b> exists.<br>Do you want to overwrite it?</qt>").arg(projectFileName), i18n("Overwrite project")) == KMessageBox::No)
          {
            projectFileName = "";
            ok = false;
            retry = true;
          }
        }
      } else
        projectFileName = "";
    } else
    {
      int choice = KMessageBox::questionYesNoCancel(this, i18n("Do you want to save the project?"), i18n("Save project"), KGuiItem(i18n("&Save"), BarIconSet("filesave")), KGuiItem(i18n("Save &as..."), BarIconSet("filesaveas")));
      if (choice == KMessageBox::No) //Save As
      {
        projectFileName = KFileDialog::getSaveFileName(QFileInfo(KalleryGlobals::ref()->options.fileName).dirPath(),"*.kallery\n*|All files",this,i18n("Save project"));

        if (QFileInfo(projectFileName).exists())
        {
          if (KMessageBox::questionYesNo(this, i18n("<qt>The file <b>%1</b> exists.<br>Do you want to overwrite it?</qt>").arg(projectFileName), i18n("Overwrite project")) == KMessageBox::No)
          {
            projectFileName = "";
            ok = false;
            retry = true;
          }
        }
      } else
      if (choice == KMessageBox::Cancel) // Do not save
        projectFileName = "";
    }
      
    if (!projectFileName.isEmpty())
    {
      if (QFileInfo(projectFileName).extension().isEmpty())
      {
        projectFileName += ".kallery";
      }
      ok = KalleryFunctions::ref()->saveProject(projectFileName);
      if (!ok)
      {
        if (KMessageBox::warningYesNo(this, i18n("There was an error when trying to save the project. Do you want to retry and possibly choose another location?"), i18n("Project Saving Error")) == KMessageBox::No)
          ok = true;
      } else
        projectSaved = true;
    } else
      if (!retry)
        ok = true; //do not save
  }
  
  progress = new QProgressDialog(i18n("Converting..."), i18n("Cancel"),
                                 2 * KalleryGlobals::ref()->options.imageList.count(), 
                                 this, "prg", true);
  progress->show();
  progress->setCaption(i18n("Converting..."));
  progress->setProgress(1);
  kapp->processEvents(QEventLoop::ExcludeSocketNotifiers);
  if (!KalleryFunctions::ref()->convertImages(progress))
  {
    delete progress;
    kapp->deref();
    DestroyMagick();
    return;
  }

  progress->setCaption(i18n("Creating web pages..."));
  progress->setLabelText("");
  KalleryFunctions::ref()->createHtmls(progress);

  if (projectSaved)
    KalleryFunctions::ref()->writeDescriptions(KalleryGlobals::ref()->projectBaseDir() + "/" + KalleryGlobals::ref()->options.descFile, KalleryGlobals::ref()->options.descList);

  delete progress;

  if (KMessageBox::questionYesNo(this,i18n("The image gallery was generated. Do you want to open it in your browser?"), i18n("Game over"), KGuiItem(i18n("&Open"), BarIconSet("konqueror")), KGuiItem(i18n("E&xit"), BarIconSet("no"))) == KMessageBox::Yes)
    kapp->invokeBrowser(KalleryGlobals::ref()->options.galleryFile, "");

  kapp->deref();
  DestroyMagick();
  KWizard::accept();
}

void Kallery::reject()
{
  if (KMessageBox::warningYesNo(this, i18n("Cancel means that you will loose all your changes. Do you want to abort the wizard?"), i18n("Confirm exit")) == KMessageBox::Yes)
  {
    kapp->deref();
    KWizard::reject();
  }
}

void Kallery::slotProjectLoaded()
{
  QString projectFileName = " - "+QFileInfo(KalleryGlobals::ref()->options.projectFileName).baseName();
  setCaption(i18n("Kallery wizard")+projectFileName);
  next();
}

void Kallery::slotPageHasChanged(const QString &title)
{
  kdDebug() << "Current page will be: " << title << endl;

  WizardPageBase *page = dynamic_cast<WizardPageBase*>(currentPage());
  if (page)
    page->setupPage();
}

void Kallery::slotShowHelp()
{
  WizardPageBase *page = dynamic_cast<WizardPageBase*>(currentPage());
  if (page)
    page->invokeHelp();
}

void Kallery::slotResult(KIO::Job *job)
{
  if (job->error())
    job->showErrorDialog();
  kapp->deref();
}

#include "kallery.moc"
