/******************************************************
 **
 **   Created : December 2003
 **        by : Varol Okan
 ** Copyright : (c) Varol Okan
 **   License : GPL v 2.0
 **
 *****************************************************/

#include <signal.h>
#include <stdlib.h>
#include <getopt.h>
#ifdef QDVD_LINUX 
#include <unistd.h>
#endif

#include <qapplication.h>
#include <qtextcodec.h>
#include <qfileinfo.h>
#include <qdir.h>

#include "CONFIG.h"

#include "log.h"
#include "global.h"
#include "dvdmenu.h"
#include "messagebox.h"
#include "qdvdauthor.h"
#include "importkino.h"
#include "cachethumbs.h"
#include "xml_dvdauthor.h"
#include "importdvdauthor.h"

#include "../bugs_workaround.h"

#ifndef XINIT_THREADS_CRASH
#include <X11/Xlib.h>
#endif

void displayHelp ()
{
  printf ("qdvdauthor -k -d -p -x -o -h\n"
	  "Copyrighted 2003-2007 by Varol Okan\n"
	  "Built " __DATE__ "\n\n"
	  "-k <inputFile>              This option allows you to import a kino smil file.\n"
	  "-d <inputFile>              This option allows you to import a dvdauthor.xml file.\n"
	  "-s <File1 File2 ... FileN>  This option allows you to import spumux.xml file(s).\n"
	  "-p <inputFile>              This option allows you to open a 'Q' DVD-Author project file.\n"
	  "-o <outputFile>             This option exports the generated 'Q' DVD-Author project file.\n"
	  "-a                          This option creates a menu structure automatically from the input provided.\n"
	  "-x                          Execute the program without Dialog boxes. This way you can run it in batch mode.\n" 
	  "                            Note: -a and -x are not yet implemented.\n\n");
}

int main( int argc, char ** argv )
{
#ifndef XINIT_THREADS_CRASH
  // XInitThreads was causing some hangs on some machines under certain circumstances. lets see if it works without.
  // Note XinitThreads is/was required for the xine libs.
  // One of the first things we ought to do is to ensure threating is turned on ...
  if ( !getenv ( "QDVD_NO_XINIT" ) ) {
    if (!XInitThreads ())	{
      QApplication::beep();
      MessageBox::warning(NULL, QObject::tr ("XInitThreads failed!"), QObject::tr ("XInitThreads failed!"), QMessageBox::Ok, QMessageBox::NoButton);
      return -1;
    }
  }
#endif

  // dvdauthor now requires this env variable to be set.
//  if ( ! getenv ( "VIDEO_FORMAT" ) )
//         setenv ( "VIDEO_FORMAT", "NTSC", 1 );

	int       iReturn = 0; 
	bool      bSkipAutosaveTest = false;
	bool      bNoMoreInputFiles = false;
	bool      bImportDVDAuthor  = false;
	bool      bSaveProjectFile  = false;
	QFileInfo fileInfo;
	QString   qsFileName;

	char *pLogLevel = getenv ("LOG_LEVEL");
	if ( pLogLevel ) 
	  Global::pLogObject = new Log ( (Log::type)atoi (pLogLevel) );
	else
	  Global::pLogObject = new Log ( Log::logDebug );
#ifdef QDVD_LINUX
	signal(SIGTTOU, SIG_IGN);
#endif
	QApplication application( argc, argv );

#ifdef SYSTEM_DIRECTORY
	Global::qsSystemPath = QString ( SYSTEM_DIRECTORY );
#endif
	if ( getenv ( "QDVD_SYSTEM_PATH" ) )
		Global::qsSystemPath = getenv ( "QDVD_SYSTEM_PATH" );

	Global::pThumbsCache = new Cache::Thumbs;

	// translation file for Qt
	QTranslator qt( 0 );
	// Under $QTDIR/translations/
	qt.load( QString( "qt_" ) + QTextCodec::locale(), "." );
	application.installTranslator( &qt );

	QDVDAuthor dvdAuthor;
	Global::pApp = &dvdAuthor;
	VMGMenu *pDVDMenu = new VMGMenu ( &dvdAuthor );

	dvdAuthor.addDVDMenu ( pDVDMenu, true );
	dvdAuthor.show ( );

	CXmlDVDAuthor theXmlStructure;
	QValueList<CXmlSpumux *>spumuxList;

	while (1) {
	  char c =  (getopt ( argc, argv, "k:axp:o:s:?hd:"));
	  if ( c == -1 )
	    break;
	  switch (c) {
	  case 'k': {  // Command line option to import a kino - file
	    // Note that a kino import is only one SourceFileEntry and not a whole DVD structure.
	    // In other words, we can have more then only one of'em.
	    if ( bNoMoreInputFiles )
	      break;
	    qsFileName = QString         ( optarg );
	    fileInfo.setFile         ( qsFileName );
	    Global::qsCurrentPath = fileInfo.dirPath ( true );
	    Import::Kino theImporter ( &dvdAuthor );
	    theImporter.import       ( qsFileName );
	    dvdAuthor.appendSourceFileEntry ( theImporter.getEntry () );
	    bSkipAutosaveTest = true;
	  }
	  break;
	  case 'd': {  // Command line option to import a dvdauthor - file
	    if ( bNoMoreInputFiles )
	      break;
	    qsFileName = QString        ( optarg );
	    fileInfo.setFile        ( qsFileName );
	    Global::qsCurrentPath = fileInfo.dirPath ( true );
	    theXmlStructure.readXml ( qsFileName );
	    bSkipAutosaveTest = true;
	    bImportDVDAuthor  = true;
	  }
	  break;
	  case 's': {  // Importing a list of spumux files
	    if ( bNoMoreInputFiles )
	      break;
	    qsFileName = QString ( optarg );
	    CXmlSpumux *pSpumux = new CXmlSpumux;
	    pSpumux->readXml ( qsFileName );
	    spumuxList.append   ( pSpumux );
	  }
	  break;
	  case 'p': {  // command line option to import a project file
	    if ( bNoMoreInputFiles )
	      break;
	    qsFileName = QString   ( optarg );
	    fileInfo.setFile   ( qsFileName );
	    Global::qsCurrentPath = fileInfo.dirPath ( true );
	    dvdAuthor.fileOpen ( qsFileName );
	    bSkipAutosaveTest = true;
	    bNoMoreInputFiles = true;
	  }
	  break;  
	  case 'x': { // execute without asking
	  }
	  break;
	  case 'a': { // autmomatically create menus from input material
	  }
	  break;
	  case 'o': { // save generated project file as ...
	    qsFileName  = QString ( optarg );
	    Global::qsProjectFileName = qsFileName;
	    bSaveProjectFile = true;
	  }
	  break;
	  case '?': 
	  case 'h': { // Print help message.
	    displayHelp ();
	    exit (0);
	  }
	  break;
	  }
	}
	dvdAuthor.postInit ( bSkipAutosaveTest );

	if ( bImportDVDAuthor ) {
	  Import::DVDAuthor importDVDAuthor     ( &dvdAuthor );
	  importDVDAuthor.buildFromDVDAuthorXML ( &theXmlStructure, spumuxList );
	  dvdAuthor.importDvdauthor ( &importDVDAuthor );
	}

	if ( bSaveProjectFile )
	  dvdAuthor.fileSave ( Global::qsProjectFileName );

	// And finally clean up the allocated memory.
	for ( uint t=0;t<spumuxList.count();t++)
	  delete spumuxList[t];
	spumuxList.clear ();

	application.connect( &application, SIGNAL( lastWindowClosed() ), &application, SLOT( quit() ) );
	iReturn = application.exec();

	// Free global static allocated objects.
	delete Global::pLogObject;
	Global::pLogObject = NULL;

	delete Global::pThumbsCache;
	Global::pThumbsCache = NULL;

	return iReturn;
}

