#include "qgrunsession.h"

#include "qglogger.h"

#include <QDir>
#include <QFileInfo>
#include <QFile>
#include <QDateTime>

#include <QMessageBox>

#include <QDebug>

static QgRunSession* defSession;

class DirCx: public QDir
{
public:
};

class QgRunSession::Implementation
{
public:
  QgLogger logger;
  DirCx workDir;
  DirCx outDir;
  DirCx sessionDir;

  QString sessionName;

  bool outValid;
  bool outEnable;

  bool interactive;

  Implementation():
      logger("GS")
  {
  }
};

QgRunSession::QgRunSession(const QString & name):
  p_(*new Implementation)
{
  setObjectName(name);
  p_.workDir.setPath(QDir::currentPath());
  p_.outDir.setPath("out");
  p_.sessionName="current";
  p_.sessionDir.setPath("out/current");
  p_.outEnable=false;
  p_.outValid=false;
  p_.interactive=false;
}

QgRunSession::~QgRunSession()
{
}

QgRunSession& QgRunSession::defaultSession()
{
  if (!defSession)
  {
    defSession=new QgRunSession("qgDefaultRunSession");
  }

  return *defSession;
}

QString QgRunSession::currentDirPath() const
{
  return QDir::currentPath();
}

const QDir& QgRunSession::workDir() const
{
  return p_.workDir;
}
const QDir& QgRunSession::outDir() const
{
  return p_.outDir;
}

const QDir& QgRunSession::sessionDir() const
{
  return p_.sessionDir;
}

void QgRunSession::setWorkDirPath(const QString &path_)
{
  QString path=QDir::cleanPath(path_);
  QString oldPath=p_.workDir.absolutePath();
  bool ok=QDir::setCurrent(path);
  if (!ok)
  {
    QString msg=QString("FAIL setWorkDirPath(%1)").arg(path);
    qErrnoWarning(msg.toLatin1().constData());
    if (p_.interactive)
    {
      QMessageBox::warning(0, "RunSession: Invalid Working Directory", QString("Invalid working directory %1").arg(path));
    }
  }
  p_.workDir.setPath(QDir::currentPath());
  if (oldPath!=p_.workDir.absolutePath())
  {
    p_.logger.debug("Working Directory", p_.workDir.absolutePath());
    emit workDirChanged();
    if (p_.outDir.isRelative())
      setOutDirPath(outDirPath());
  }
}

QString QgRunSession::workDirPath() const
{
  return p_.workDir.path();
}

void QgRunSession::setOutDirPath(const QString & path_)
{
  QString path=QDir::cleanPath(path_);
  QString oldPath=p_.outDir.absolutePath();
  p_.outDir.setPath(path);
  if (oldPath!=p_.outDir.absolutePath())
  {
    p_.logger.debug("Output Directory", p_.outDir.absolutePath());
    emit sessionDirChanged();

    if (p_.sessionDir.isRelative())
      setSessionDirPath(p_.sessionName);
  }
}

QString QgRunSession::outDirPath() const
{
  return p_.outDir.path();
}

void QgRunSession::setSessionDirPath(const QString &path_)
{
  //QString path=QDir::cleanPath(path_);
  QFileInfo info(path_);
  QString path=info.fileName();
  if (path.contains("%1"))
  {
    path=QString(path).arg(QDateTime::currentDateTime().toString("yyyy-MM-dd-hh_mm-ss"));
  }
  if (info.isAbsolute() || path!=path_)
  {
    p_.logger.warning(QString("Session path sould be relative. Only \"%1\" considered").arg(path), path_);
  }
  //QString oldPath=p_.sessionDir.absolutePath();
  p_.sessionName=path;
  p_.sessionDir=p_.outDir;
  //p_.sessionDir.cd(path);
  p_.sessionDir.setPath(p_.outDir.path()+"/"+path);

  //if (oldPath!=p_.sessionDir.absolutePath())
  {
    p_.logger.debug("Session Directory", p_.sessionDir.absolutePath());
    emit sessionDirChanged();
  }
}

QString QgRunSession::sessionDirPath() const
{
  return p_.sessionDir.path();
}

bool QgRunSession::outValid() const
{
  return p_.outValid;
}

void QgRunSession::setOutValid(bool valid)
{
  bool old=p_.outValid;
  bool old_ena=outEnable();
  p_.outValid=valid;
  if (old!=valid)
    emit outValidChanged(valid);
  if (old_ena!=outEnable())
    emit outEnableChanged(outEnable());
}

bool QgRunSession::outEnable() const
{
  return p_.outEnable && p_.outValid;
}

void QgRunSession::setOutEnable(bool enable)
{
  bool old=outEnable();
  p_.outEnable=enable;

  if (old!=outEnable())
    emit outEnableChanged(outEnable());
}

//enum OutValidationFlags { OutDirNoCreate, OutDirCreate, OutDirCreateOnDemand};

bool QgRunSession::validateOutputDirectory(OutValidationFlags f)
{
  int need_create=0;
  //setOutValid(false);

  QFileInfo info(p_.outDir.path());
  if (p_.outDir.exists())
  {
    if (!info.isDir() || !info.isWritable())
      return false;
  }
  else
    need_create=1;

  if (!need_create)
  {
    info.setFile(p_.sessionDir.path());
    if (info.exists())
    {
      if (!info.isDir() || !info.isWritable())
      {
        setOutValid(false);
        return false;
      }
    }
    else
      need_create=2;
  }

  if (need_create)
  {
    if (f==OutDirCreateOnDemand)
    {
      QMessageBox::StandardButton res=QMessageBox::question(0, "RunSession", QString("Create sessiondirectory %1 ?").arg(p_.sessionDir.absolutePath()), QMessageBox::Yes|QMessageBox::No);
      if (res!=QMessageBox::Yes)
      {
        setOutValid(false);
        return false;
      }
    }
    else if (f!=OutDirCreate)
    {
      setOutValid(false);
      return false;
    }
    bool ok=p_.sessionDir.mkpath(p_.sessionDir.absolutePath());
    if (!ok)
    {
      QString msg=QString("FAIL mkpath(%1)").arg(p_.sessionDir.absolutePath());
      qErrnoWarning(msg.toLatin1().constData());
      if (f==OutDirCreateOnDemand) //p_.interactive)
      {
        QMessageBox::warning(0, "RunSession: Invalid Session Directory", QString("Cannot create directory %1").arg(p_.sessionDir.absolutePath()));
      }
      setOutValid(false);
      return false;
    }
  }

  setOutValid(true);
  return true;
}


QString QgRunSession::checkArg(const QString& arg, const QString &prefix)
{
  QString tmp;
  if (arg.startsWith(prefix))
  {
    tmp=arg;
    tmp=tmp.remove(prefix);
  }
  return tmp;
}

bool QgRunSession::parseStandardArguments(QStringList &lst, bool interactive)
{
  QStringList purgedList;
  p_.interactive=interactive;

  foreach(QString arg, lst)
  {
    if (arg.startsWith("-cx:wd="))
    {
      arg.remove("-cx:wd=");
      setWorkDirPath(arg);
      continue;
    }
    if (arg.startsWith("-cx:out="))
    {
      arg.remove("-cx:out=");
      setOutDirPath(arg);
      continue;
    }
    purgedList.append(arg);
  }
  p_.interactive=false;
  lst=purgedList;

  return true;
}


#if 0
bool create_dirs=false;

if (!workingDirectory.isEmpty())
{
  bool res=QDir::setCurrent(workingDirectory);
  if (!res)
    qgLogger().logError(QString("FAILED QDir::setCurrentDir(%1)").arg(workingDirectory));
}
qgLogger().logInfo(QString("Working directory: %1").arg(QDir::currentPath()));
QFileInfo outDir(outBaseDirectory);

if (outDir.exists())
{
  if (!outDir.isDir())
  {
    QMessageBox::warning(this, "Invliad output directory", "Output directory exists and it is a file. Result storing disabled");
  }
  QDir tmp(outDir.filePath());
  tmp.cd(outSessionDirectory);
  if (tmp.exists())
}
else
{
  StandardButton rs=QMessageBox::question(this, "Output Directory doesn't exit", "Create it?", QMessageBox::Yes|QMessageBox::No);
  create_dir=res==QMessageBox::Yes;
}
#endif
