//
// This file is part of MorphoGraphX - http://www.MorphoGraphX.org
// Copyright (C) 2012-2015 Richard S. Smith and collaborators.
//
// If you use MorphoGraphX in your work, please cite:
//   http://dx.doi.org/10.7554/eLife.05864
//
// MorphoGraphX is free software, and is licensed under under the terms of the 
// GNU General (GPL) Public License version 2.0, http://www.gnu.org/licenses.
// 
#include "MorphoGraphX.hpp"
#include <QApplication>
#include <QString>
#include <QGLFormat>
#include <QDir>
#include <QFileInfo>
#include <QMetaType>
#include <QTimer>
#include "Information.hpp"
#include <QMessageBox>
#include <QStringBuilder>
#include "Dir.hpp"
#include "Thrust.hpp"
#include "Version.hpp"
#include "Random.hpp"

using std::cin;
using mgx::Information::out;

int main(int argc, char** argv)
{
  QCoreApplication::setOrganizationDomain("morphographx.org");
  QCoreApplication::setOrganizationName("MorphoGraphX");
  QCoreApplication::setApplicationName("MorphoGraphX");
  QCoreApplication::setApplicationVersion(VERSION);

  bool noGui = false;
  bool isDebug = false;
  bool showHelp = false;
  bool showAppdir = false;
  bool showProcessdir = false;
  bool showUserprocessdir = false;
  bool showAllprocessdir = false;
  bool showIncludedir = false;
  bool showLibsdir = false;
  bool showVersion = false;
  bool showResource = false;
  bool setModel = false;
  bool autoRun = false;
  QString filename, modelPath;
  QStringList addLibraries;

  for(int i = 1; i < argc; ++i) {
    QString arg = QString::fromLocal8Bit(argv[i]);
    if(arg == "--debug")
      isDebug = true;
    else if((arg == "--help")or (arg == "-h")) {
      showHelp = true;
      noGui = true;
      break;
    } else if(arg == "--dir") {
      showAppdir = true;
      noGui = true;
      break;
    } else if(arg == "--process") {
      showProcessdir = true;
      noGui = true;
      break;
    } else if(arg == "--user-process") {
      showUserprocessdir = true;
      noGui = true;
      break;
    } else if(arg == "--all-process") {
      showAllprocessdir = true;
      noGui = true;
      break;
    } else if(arg == "--include") {
      showIncludedir = true;
      noGui = true;
      break;
    } else if(arg == "--lib") {
      showLibsdir = true;
      noGui = true;
      break;
    } else if(arg == "--version") {
      showVersion = true;
      noGui = true;
      break;
    } else if(arg == "--resource") {
      showResource = true;
      noGui = true;
      break;
    } else if(arg == "--model") {
      setModel = true;
      if(++i < argc)
        modelPath = QString::fromLocal8Bit(argv[i]);
      else {
        showHelp = true;
        break;
      }
    } else if(arg == "--addlibrary") {
      if(++i < argc) {
	      QString libToAdd = QString::fromLocal8Bit(argv[i]);
	      addLibraries << libToAdd;
      }
      else {
        showHelp = true;
        break;
      }
    } else if(arg == "--run") {
      autoRun = true;
    }
    else if(filename.isEmpty()) {
      filename = arg;
      QString currdir = QFileInfo(filename).dir().path();
      if(currdir.length() > 0)
        mgx::setCurrentPath(currdir);
    }
  }

  if(showHelp) { out 
    << "Usage: MorphoGraphX [<Command>] | [--debug] [--addlibrary LibraryPath] [--model ModelPath [--run]] [FILE.mgxv]\n"
       "  Flags:\n"
       "    --debug        - Launch MorphoGraphX in debug mode\n"
       "    --model        - set the model/process\n"
       "    --run          - runs the model/process automatically\n"
       "    --addlibrary   - adds a process library to MorphoGraphX\n"
       "  Commands:\n"
       "    --dir          - Print the application directory and exit\n"
       "    --process      - Print the process directory and exit\n"
       "    --user-process - Print the user process directory and exit\n"
       "    --all-process  - Print all the directories searched for processes and exit\n"
       "    --resource     - Print the resource directory and exit\n"
       "    --include      - Print the include directory and exit\n"
       "    --lib          - Print the library directory and exit\n"
       "    --version      - Display the version and revision and exit\n"
       "    --help |-h     - Print this help" << endl;
    return 0;
  } 

  QCoreApplication* app = 0;
  if(noGui)
    app = new QCoreApplication(argc, argv);
  else
    app = new QApplication(argc, argv);

  if(showAppdir) {
    out << QCoreApplication::applicationDirPath() << endl;
    return 0;
  } else if(showProcessdir) {
    // FIXME: this only shows one arbitrary path
    out << mgx::processDirs()[0].absolutePath() << endl;
    return 0;
  } else if(showUserprocessdir) {
    // FIXME: this only shows one arbitrary path
    out << mgx::userProcessDirs()[0].absolutePath() << endl;
    return 0;
  } else if(showAllprocessdir) {
    QList<QDir> dirs = mgx::processDirs();
    forall(const QDir& dir, dirs)
      out << dir.absolutePath() << endl;
    return 0;
  } else if(showIncludedir) {
    out << mgx::includeDir().path() << endl;
    return 0;
  } else if(showLibsdir) {
    out << mgx::libDir().path() << endl;
    return 0;
  } else if(showResource) {
    out << mgx::resourceDir().path() << endl;
    return 0;
  } else if(showVersion) {
    out << "MorphoGraphX version " VERSION " rev. " REVISION << endl;
    return 0;
  }

  // Unfortunately, once you turn multisampling on, it seems to be impossible to turn it off.
  // This screws up selection by color.
  QGLFormat format = QGLFormat::defaultFormat();
  format.setSampleBuffers(false);
  //format.setVersion(3,0);
  QGLFormat::setDefaultFormat(format);

  // Register extra meta type
  qRegisterMetaType<floatList>("floatList");
  qRegisterMetaTypeStreamOperators<floatList>("floatList");

  mgx::DEBUG = isDebug;
  out << "Welcome to MorphoGraphX!" << endl;
  out << "Thrust host evaluation: " << THRUST_TAG << endl;
  out << "Thrust device evaluation: " << thrust_device_system_str(THRUST_DEVICE_SYSTEM) << endl;
  out << endl;

  // Initialize random numbers generator
  mgx::sran_time();

  MorphoGraphX* gui = new MorphoGraphX(QCoreApplication::applicationDirPath(),
				       addLibraries);
  gui->setDebug(isDebug);
  gui->show();
  if(filename.toLower().endsWith(".mgxv"))
    gui->FileOpen(filename);
  else {
    gui->setLoadFile(filename);
    QObject::connect(gui, SIGNAL(processFinished()), gui, SLOT(AutoOpen()));
    gui->FileOpen("");
  }
  if(setModel) {
    gui->setModelPath(modelPath);
    if(autoRun) {
      QObject::connect(gui, SIGNAL(processFinished()), gui, SLOT(AutoRunSlot()));
    }
  } else if(autoRun)
    out << "You cannot use --run without specifying the starting --model" << endl;

  int result = 1;
  try {
    result = app->exec();
  } catch(const QString& str) {
    out << "Unhandled exception: " << str << endl;
  }
  if(!result)
    out << "Bye bye!" << endl;
  else
    out << "Error on exit" << endl;
 
  QApplication::exit(result);

  return result;
}
