/***************************************************************************
**
**  This file is part of DinverCore.
**
**  DinverCore 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 3 of the License, or
**  (at your option) any later version.
**
**  DinverCore is distributed in the hope that it will be useful,
**  but WITHOUT ANY WARRANTY; without even the implied warranty of
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**  GNU General Public License for more details.
**
**  You should have received a copy of the GNU General Public License
**  along with Foobar.  If not, see <http://www.gnu.org/licenses/>
**
**  See http://www.geopsy.org for more information.
**
**  Created: 2009-04-21
**  Copyright: 2009-2019
**    Marc Wathelet
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include <QGpCoreTools.h>
#include "TemporaryDirectory.h"

namespace DinverCore {

/*!
  \class TemporaryDirectory TemporaryDirectory.h
  \brief Brief description of class still missing

  Full description of class still missing
*/

int TemporaryDirectory::_instanceCount=0;

/*!
  Description of constructor still missing
*/
TemporaryDirectory::TemporaryDirectory(QObject * parent)
    : QObject(parent)
{
  TRACE;  
  _instanceCount++;
  QSettings& reg=CoreApplication::instance()->settings();
  QString tempPath=reg.value("tempPath", QDir::home().absoluteFilePath(".dinvertemp")).toString();

  setPath(tempPath);
  // Write ".alive" every 10 minutes to temporary directory. On startup, dinver check always for dead instance in temporary
  // directory and clean them if "alive" is older than 20 minutes.
  keepAlive();
  _keepAlive.setInterval(600000);
  connect(&_keepAlive, SIGNAL(timeout()), this, SLOT(keepAlive()) );
  _keepAlive.start();
}

/*!
  Description of destructor still missing
*/
TemporaryDirectory::~TemporaryDirectory()
{
  TRACE;
  _keepAlive.stop();
  QStringList filters;
  filters << "*.report";
  filters << "*.param";
  filters << "*.target";
  QStringList cacheFiles=entryList(filters);
  for(QStringList::iterator it=cacheFiles.begin();it!=cacheFiles.end();it++) {
    remove(*it);
  }
  remove(".alive");
  QString name=dirName();
  cdUp();
  rmdir(name);
}

/*!
  Set the path where to store inversion outputs. The default is the home directory.
*/
void TemporaryDirectory::setPath(QString p)
{
  TRACE;
  if(p.isEmpty()) p=QDir::homePath();
  // To avoid conflicts with other dinver instances, report files are saved in
  // a sub-directory whose name is made of the application pid. This can help
  // to trace if execution is finished or not.
  QDir::setPath(p);
  if(!exists()) {
    if(!mkpath(absolutePath())) {
      Message::critical(MSG_ID, tr("Initialize temporary directory"), tr("Cannot create temporary directory %1, "
                            "check that the disk is not full and that you have sufficient permissions.").arg(absolutePath()));
      exit(2);
    }
  }
  QFileInfo fi(absolutePath());
  if(!fi.isWritable()) {
    Message::critical(MSG_ID, tr("Initialize temporary directory"), tr("Directory %1 is not writable. "
                          "Check that the disk is not full and that you have sufficient permissions.").arg(absolutePath()));
    exit(2);
  }

  QString subDir=QString::number(QCoreApplication::applicationPid())+"_"+QString::number(_instanceCount);
  if(!mkdir(subDir)) {
    Message::critical(MSG_ID, tr("Initialize temporary directory"), tr("Cannot create directory %1.").arg(absoluteFilePath(subDir)));
    exit(2);
  }
  cd(subDir);
  // Clean old instances if there are, left by crashes or previous release (before 20080603)
  clear();
}

/*!
  Called avery 10 minutes, write ".alive" to temporary directory to prevent deletion by another dinver instance
*/
void TemporaryDirectory::keepAlive()
{
  QFile f(absoluteFilePath(".alive"));
  f.open(QIODevice::WriteOnly);
}

/*!
  Clear all defunct instances
*/
void TemporaryDirectory::clear()
{
  QDir tempRoot=*this;
  tempRoot.cdUp();
  //printf("Temp root dir %s\n", tempRoot.absolutePath().toLatin1().data());
  QStringList deadInstances=tempRoot.entryList(QDir::AllDirs | QDir::NoDotAndDotDot);
  QDateTime deadLine=QDateTime::currentDateTime().addSecs(-1200);
  //printf("Deadline %s\n",deadLine.toString("hh:mm:ss").toLatin1().data());
  for(QStringList::iterator it=deadInstances.begin();it!=deadInstances.end();it++) {
    QFileInfo fi(tempRoot.absoluteFilePath(*it));
    //printf("%s modified %s\n",fi.absoluteFilePath().toLatin1().data(), fi.lastModified().toString("hh:mm:ss").toLatin1().data());
    if(fi.lastModified()<deadLine) {
      QDir d(fi.absoluteFilePath());
      fi.setFile(d.absoluteFilePath(".alive"));
      //printf("  %s modified %s\n",fi.absoluteFilePath().toLatin1().data(), fi.lastModified().toString("hh:mm:ss").toLatin1().data());
      if(fi.lastModified()<deadLine || !fi.exists()) {
        QStringList filters;
        filters << "*.report";
        filters << "*.param";
        filters << "*.target";
        QStringList cacheFiles=d.entryList(filters);
        for(QStringList::iterator it=cacheFiles.begin();it!=cacheFiles.end();it++) {
          d.remove(*it);
        }
        d.remove(".alive");
        QString name=d.dirName();
        d.cdUp();
        d.rmdir(name);
      }
    }
  }
}

} // namespace DinverCore
