//
// This file is part of MorphoGraphX - http://www.MorphoGraphX.org
// Copyright (C) 2012-2021 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 <XPIWITProcess.hpp>
#include <XPIWITParms.hpp>
#include <SystemProcessSave.hpp>
#include <SystemProcessLoad.hpp>
#include <StackProcess.hpp>

namespace mgx 
{
  bool TwangSegment::run(Stack *stack, Store* input, Store* output)
  {
    // Create a temporary directory
    QTemporaryDir tmpDir("/tmp/mgxXXXXXX");

    // Read in the xml file and set the parameters
    QDomDocument doc;
    QString xpiPath = QString("%1/XPIWIT").arg(MGXRESPATH);
    QString xmlName(xpiPath + "/XMLPipelines/TWANGSegmentation.xml");
    QFile xmlFile(xmlName);
    if(!xmlFile.open(QIODevice::ReadOnly))
      throw QString("%1 Unable to open xml file: %2").arg(name()).arg(xmlName);
    doc.setContent(&xmlFile);
    xmlFile.close();

    auto step = stack->step();
    auto origStep = step;
    double mins = step[0];
    for(int i = 0; i < 3; i++)
      if(mins > step[i])
        mins = step[i];
    step /= mins;

    XPIWITParms xpiParms;
    xpiParms.addParm("ImageReader", "SpacingX", QString::number(step.x()));
    xpiParms.addParm("ImageReader", "SpacingY", QString::number(step.y()));
    xpiParms.addParm("ImageReader", "SpacingZ", QString::number(step.z()));
    xpiParms.addParm("LoGScaleSpaceMaximumProjectionFilter", "MinSigma", QString::number(parm("Min Sigma").toFloat()));
    xpiParms.addParm("LoGScaleSpaceMaximumProjectionFilter", "MaxSigma", QString::number(parm("Max Sigma").toFloat()));
    xpiParms.addParm("ExtractLocalExtremaFilter", "StdDevMultiplicator", QString::number(parm("Std Dev Mult").toFloat()));
    xpiParms.addParm("ExtractLocalExtremaFilter", "NeighborhoodRadius", QString::number(parm("Neighborhood Radius").toInt()));
    xpiParms.update(doc);

    // Write the parameter file
    QString xmlOutName(tmpDir.path() + "/mgxPipeline.xml");
    QFile xmlOutFile(xmlOutName);
    if(!xmlOutFile.open(QIODevice::WriteOnly | QIODevice::Text))
      throw QString("%1 Unable to open xml file for writing: %2").arg(name()).arg(xmlOutName);
    xmlOutFile.write(doc.toString().toLocal8Bit());
    xmlOutFile.close();

    // Write the stack
    QString inStackName(tmpDir.path() + "/mgxStack.tif");
    Information::out << "Saving stack to :" << inStackName << endl;
    StackSave(*this).run(stack, input, inStackName, 0);

    // Run the process
    QString exeString(xpiPath + "/Bin/XPIWIT " + " --xml " + xmlOutName + " --input ""0," + inStackName + ",3,ushort"" --output " 
            + tmpDir.path() + "/");
    if(!QProcess::execute(exeString) ==  0)
      throw QString("%1 Unable to run: %2").arg(name()).arg(exeString);

    // Open the segmented nuclei
    StackOpen(*this).run(stack, output, tmpDir.path() + "/item_0006_TwangSegmentation/mgxStack_item_0006_TwangSegmentation_Out1.tif");
    ChangeVoxelSize(*this).run(stack, origStep);
    output->setFile("");
    output->show();
    output->setLabels(true);

    return true;
  }
  REGISTER_PROCESS(TwangSegment);

  bool XPIWITRun::run()
  {
    QString xpiPath = QString("%1/XPIWIT").arg(MGXRESPATH);
    QString exeString(xpiPath + "/Bin/XPIWITGUI");
    QString path = QDir::currentPath();
    QDir::setCurrent(xpiPath + "/Bin");

    QProcess p;
    if(!p.startDetached(exeString, QStringList()))
      throw QString("%1 Unable to run: %2").arg(name()).arg(exeString);

    QDir::setCurrent(path);

    return true;
  }
  REGISTER_PROCESS(XPIWITRun);

  bool XPIWITHelp::run()
  {
    QString helpFile = QString("%1/XPIWIT/XPIWITDocumentation.pdf").arg(MGXRESPATH);

    QProcess p;
    if(!p.startDetached("xdg-open", QStringList() << helpFile))
      throw QString("%1 Unable to run: %2 %3").arg(name()).arg("xdg-open").arg(helpFile);

    return true;
  }
  REGISTER_PROCESS(XPIWITHelp);
}
