/* -*- indent-tabs-mode: nil; -*-
 *
 * This file is part of the Mango recipe management distribution.
 * Copyright (c) 2000-2003, Roland Jesse
 * All rights reserved.
 *
 * For license and copyright information see the file COPYRIGHT or 
 * <http://www.opensource.org/licenses/bsd-license.html>.
 *
 * $Id: ExportDialog.cpp,v 1.12 2003/06/19 18:19:14 rjesse Exp $
 */

#include "ExportDialog.h"
#include "CMLExporter.h"
#include "MangoExporter.h"
#include "MMExporter.h"
#include "RecipeMLExporter.h"
#include "RKExporter.h"
#include "Repository.h"
#include <qfiledialog.h>
#include <qinputdialog.h>
#include <qmessagebox.h>
#include <qradiobutton.h>
#include <qtextbrowser.h>
#include <assert.h>

/*!
  Constructor.

  The dialog is modal. That's because what to export depends on actions the
  user did before opening this dialog (e.g. marking recipes or cookbooks).
  We don't want to allow for invalidating these actions before our exporting
  work is done.
*/
ExportDialog::ExportDialog( QWidget* parent, const char* name, const What& def)
   : ExportForm( parent, name, true), m_currentCookbook(0), m_markedRecipes(0)
{
   switch (def) {
	  case CURRENT_RECIPE:
		 buttonCurrentRecipe->setChecked( true);
		 break;
	  case CURRENT_COOKBOOK:
		 buttonCurrentCookbook->setChecked( true);
		 break;
	  case MARKED_RECIPES:
		 buttonMarkedRecipes->setChecked( true);
		 break;
	  case MARKED_COOKBOOKS:
		 buttonMarkedCookbooks->setChecked( true);
		 break;
	  default:					// This should never happen!
		 assert( true);
		 break;
   }
}

ExportDialog::~ExportDialog()
{
}

void
ExportDialog::enable( const What& what)
{
   switch (what) {
	  case CURRENT_RECIPE:
		 buttonCurrentRecipe->setEnabled( true);
		 break;
	  case CURRENT_COOKBOOK:
		 buttonCurrentCookbook->setEnabled( true);
		 break;
	  case MARKED_RECIPES:
		 buttonMarkedRecipes->setEnabled( true);
		 break;
	  case MARKED_COOKBOOKS:
		 buttonMarkedCookbooks->setEnabled( true);
		 break;
	  default:					// This should never happen!
		 assert( true);
		 break;
   }
}

void
ExportDialog::setCurrentRecipe( const Recipe& recipe) // public
{
   m_currentRecipe = recipe;
   enable( CURRENT_RECIPE);
}

void
ExportDialog::setCurrentCookbook( RecipeModel* cookbook) // public
{
   m_currentCookbook = cookbook;
   enable( CURRENT_COOKBOOK);
}

void
ExportDialog::setMarkedRecipes( RecipeModel* recipes) // public
{
   m_markedRecipes = recipes;
   enable( MARKED_RECIPES);
}

/*!
  Tells the export dialog object that we are exporting a set of user selected
  (marked) cookbooks and which ones these are.
*/
void
ExportDialog::setMarkedCookbooks( const QDict<RecipeModel> cbs)
{
   m_markedCookbooks.resize( cbs.size());
   m_markedCookbooks = cbs;
   enable( MARKED_COOKBOOKS);
}

/*!
  Return user's selection of what to export.
  
  Only for internal use.
*/
ExportDialog::What
ExportDialog::getWhat() const   // private
{
   What ret = UNDEF_WHAT;
   
   if (buttonCurrentRecipe->isChecked())
      ret = CURRENT_RECIPE;
   else if (buttonCurrentCookbook->isChecked())
      ret = CURRENT_COOKBOOK;
   else if (buttonMarkedRecipes->isChecked())
      ret = MARKED_RECIPES;
   else if (buttonMarkedCookbooks->isChecked())
      ret = MARKED_COOKBOOKS;

   return ret;
}

/*! Return in which format the export should be done.

  Only for internal use.
*/
ExportDialog::Format
ExportDialog::getFormat() const // private
{
   Format ret = UNDEF_FORMAT;
   
   if (buttonMango->isChecked())
      ret = MANGO;
   else if (buttonMealMaster->isChecked())
      ret = MEALMASTER;
   else if (buttonCookML->isChecked())
      ret = COOKML;
   else if (buttonRecipeML->isChecked())
      ret = RECIPEML;
   else if (buttonRezKonv->isChecked())
      ret = REZKONV;

   return ret;
}

void
ExportDialog::startExport()     // public
{
   What what = getWhat();
   Format format = getFormat();

   if (format == UNDEF_FORMAT) {
      QMessageBox::critical( this, tr( "No format selected."),
                             tr( "Please select an export format!"),
                             QMessageBox::Ok, QMessageBox::NoButton);
      return;
   }
   
   switch (what) {
      case CURRENT_RECIPE:
         exportCurrentRecipe( format);
         break;
      case CURRENT_COOKBOOK:
         exportCurrentCookbook( format);
         break;
      case MARKED_RECIPES:
         exportMarkedRecipes( format);
         break;
      case MARKED_COOKBOOKS:
         exportMarkedCookbooks( format);
         break;
      default:                  // never!
         assert( true);
         break;
   }
}

void
ExportDialog::exportCurrentRecipe( const Format& format) // private
{
   Exporter* exporter;
   QString startWith( m_currentRecipe.title());
   switch (format) {
   case MANGO:
      exporter = new MangoExporter( m_currentRecipe);
      startWith.append( ".mango");
      break;
   case MEALMASTER:
      exporter = new MMExporter( m_currentRecipe);
      startWith.append( ".mm");
      break;
   case COOKML:
      exporter = new CMLExporter( m_currentRecipe);
      startWith.append( ".cml");
      break;
   case RECIPEML:
      exporter = new RecipeMLExporter( m_currentRecipe);
      startWith.append( ".RecipeML");
      break;
   case REZKONV:
      exporter = new RKExporter( m_currentRecipe);
      startWith.append( ".rk");
      break;
   default:
      assert( true);
      break;
   }
   QString ext = exporter->getExtensions();
   QString path = QFileDialog::getSaveFileName( tr( startWith), tr( ext));
   exporter->setFileName( path);
   try {
      exporter->apply();
   }
   catch (Error& e) {
      logError( e.what());
   }
   logRecipesSaved( 1, path);
}

void
ExportDialog::exportCurrentCookbook( const Format& format) // private
{
   exportCookbook( m_currentCookbook, format);
}

void
ExportDialog::exportMarkedRecipes( const Format& format) // private
{
   exportCookbook( m_markedRecipes, format);
}

/*!
  Export cookbooks that the user selected for export.
  \sa setMarkedCookbooks()
*/
void
ExportDialog::exportMarkedCookbooks( const Format& format) // private
{
   QString newName = QInputDialog::getText(
      tr( "Mango - Export of multiple cookbooks"),
      tr( "A new cookbook will be created out of all marked cookbooks. Please enter a nice and fancy name for it."));
   RecipeModel* newCookbook = new RecipeModel( newName);
   QDictIterator<RecipeModel> it( m_markedCookbooks);
   for(; it.current(); ++it) {
      *newCookbook += *(it.current());
   }

   exportCookbook( newCookbook, format);
}

void
ExportDialog::exportCookbook( RecipeModel* cookbook, 
                              const Format& format) // private
{
   QString ext;
   Exporter* exporter;
   switch (format) {
   case MANGO:
      exporter = new MangoExporter( cookbook);
      break;
   case MEALMASTER:
      exporter = new MMExporter( cookbook);
      break;
   case COOKML:
      exporter = new CMLExporter( cookbook);
      break;
   case RECIPEML:
      exporter = new RecipeMLExporter( cookbook);
      break;
   case REZKONV:
      exporter = new RKExporter( cookbook);
      break;
   default:
      assert( true);
      break;
   }
   ext = exporter->getExtensions();
   QString path = QFileDialog::getSaveFileName( cookbook->getName(), ext);
   exporter->setFileName( path);
   try {
      exporter->apply();
      /* Mango is the default file format. */
      if (format == MANGO) { cookbook->setFileName( path); }
   }
   catch (Error& e) {
      logError( e.what());
   }
   delete exporter;
   logRecipesSaved( cookbook->getRecipeList().size(), path);

   Repository* repo = Repository::getInstance();
   if (!repo->hasCookbook( cookbook->getName())) {
      repo->insertCookbook( cookbook);
      QString str( tr( "The export resulted in the new cookbook named "));
      str.append( cookbook->getName());
      textBrowserLogbook->append( str);
   }
}

/*!
  Append \a text to the log widget.
*/
void
ExportDialog::logError( const QString& text) // private
{
   QString str( text);
   str.prepend( tr( "Error during export: "));
   textBrowserLogbook->append( str);
}

void
ExportDialog::logRecipesSaved( int num, const QString& fname) // private
{
   QString str;
   str.append( tr( "%1 recipe(s) successfully saved in file %2.",
                   "Argument 1 is substituted by the number of recipes, "
                   "argument 2 is substituted by the saved file name.")
               .arg( num) .arg( fname));
   textBrowserLogbook->append( str);
}
