#include "Isis.h"
#include "ProcessImportPds.h"
#include "UserInterface.h"
#include "FileName.h"
#include "Pvl.h"
#include "IException.h"
#include "TextFile.h"
#include <QString>

using namespace std;
using namespace Isis;

void TranslateLunarLabels(FileName &labelFile, Cube *ocube);

void IsisMain() {
  ProcessImportPds p;
  Pvl label;
  UserInterface &ui = Application::GetUserInterface();
  FileName in = ui.GetFileName("FROM");

  //Checks if in file is rdr
  label = in.expanded();
  if(label.hasObject("IMAGE_MAP_PROJECTION")) {
    QString msg = "[" + in.name() + "] appears to be an rdr file.";
    msg += " Use pds2isis.";
    throw IException(IException::User, msg, _FILEINFO_);
  }

  p.SetPdsFile(in.expanded(), "", label);
  Cube *ocube = p.SetOutputCube("TO");
  p.StartProcess();
  TranslateLunarLabels(in, ocube);
  p.EndProcess();

  return;
}

void TranslateLunarLabels(FileName &labelFile, Cube *ocube) {

  // Get the directory where the Lunar translation tables are.
  PvlGroup &dataDir = Preference::Preferences().findGroup("DataDirectory");

  // Transfer the instrument group to the output cube
  QString transDir = (QString) dataDir["Lo"] + "/translations/";
  Pvl inputLabel(labelFile.expanded());
  FileName transFile;
  FileName bandBinTransFile;

  bool hasFiducial = false;
  // Check to see if file is PDS
  if(inputLabel.hasKeyword("PDS_VERSION_ID", Pvl::None)) {
    QString pdsVersion = inputLabel.findKeyword("PDS_VERSION_ID", Pvl::None)[0];

    if(pdsVersion == "PDS3") {
      if(inputLabel.hasKeyword("LO:FIDUCIAL_ID", Pvl::Traverse)) {
        hasFiducial = true;
        bandBinTransFile = transDir + "LoPdsFiducialImport.trn";
      }
      else if(inputLabel.hasKeyword("LO:BORESIGHT_SAMPLE", Pvl::Traverse)) {
        bandBinTransFile = transDir + "LoPdsBoresightImport.trn";
      }
      else {
        QString msg = "[" + labelFile.name() + "] does not contain boresight or fiducial information";
        throw IException(IException::User, msg, _FILEINFO_);
      }
    }
    else {
      QString msg = "[" + labelFile.name() + "] contains unknown PDS version [" +
                   pdsVersion + "]";
      throw IException(IException::User, msg, _FILEINFO_);
    }
  }
  // Else the input is an Isis2 cube
  else {
    if(inputLabel.hasKeyword("FIDUCIAL_ID", Pvl::Traverse)) {
      hasFiducial = true;
      bandBinTransFile = transDir + "LoIsis2FiducialImport.trn";
    }
    else if(inputLabel.hasKeyword("BORESIGHT_SAMPLE", Pvl::Traverse)) {
      bandBinTransFile = transDir + "LoIsis2BoresightImport.trn";
    }
    else {
      QString msg = "[" + labelFile.name() + "] does not contain boresight or fiducial information";
      throw IException(IException::User, msg, _FILEINFO_);
    }
  }

  transFile = transDir + "LoGeneralImport.trn";
  // Get the translation manager ready
  PvlToPvlTranslationManager commonlabelXlater(inputLabel, transFile.expanded());
  // Pvl outputLabels;
  Pvl *outputLabel = ocube->label();
  commonlabelXlater.Auto(*(outputLabel));

  PvlToPvlTranslationManager labelXlater(inputLabel, bandBinTransFile.expanded());
  labelXlater.Auto(*(outputLabel));

  PvlGroup &inst = outputLabel->findGroup("Instrument", Pvl::Traverse);

  //Creates FiducialCoordinateMicron with the proper units
  if(!inputLabel.hasKeyword("LO:BORESIGHT_SAMPLE", Pvl::Traverse)) {
    QString fcm = (QString) inst.findKeyword("FiducialCoordinateMicron");
    QString fcmUnits = fcm;
    fcmUnits.remove(QRegExp("^[0-9.]*"));
    fcm.remove(QRegExp("[a-zA-Z]*$"));
    inst.findKeyword("FiducialCoordinateMicron").setValue(fcm, fcmUnits);
  }

  // High Resolution & Fiducial Medium Case
  if(hasFiducial) {
    //Add units to some keywords
    PvlKeyword fxc = inst.findKeyword("FiducialXCoordinates");
    inst.findKeyword("FiducialXCoordinates").clear();
    for(int i = 0; i < fxc.size(); i++) {
      inst.findKeyword("FiducialXCoordinates").addValue(fxc[i], "mm");
    }

    PvlKeyword fyc = inst.findKeyword("FiducialYCoordinates");
    inst.findKeyword("FiducialYCoordinates").clear();
    for(int i = 0; i < fyc.size(); i++) {
      inst.findKeyword("FiducialYCoordinates").addValue(fyc[i], "mm");
    }

    PvlKeyword fl = inst.findKeyword("FiducialLines");
    inst.findKeyword("FiducialLines").clear();
    for(int i = 0; i < fl.size(); i++) {
      inst.findKeyword("FiducialLines").addValue(fl[i], "pixels");
    }

    PvlKeyword fs = inst.findKeyword("FiducialSamples");
    inst.findKeyword("FiducialSamples").clear();
    for(int i = 0; i < fs.size(); i++) {
      inst.findKeyword("FiducialSamples").addValue(fs[i], "pixels");
    }
  }
  else if(!hasFiducial) {
    //What needs to be done if it contains Boresight info
  }

  QString instrumentID = inst.findKeyword("InstrumentId");
  QString spacecraftName = inst.findKeyword("SpacecraftName");

  //Determines the NaifFrameCode
  PvlGroup kerns("Kernels");
  QString frameCode;
  if(spacecraftName.compare("Lunar Orbiter 3") == 0) {
    frameCode = "-533";
  }
  else if(spacecraftName.compare("Lunar Orbiter 4") == 0) {
    frameCode = "-534";
  }
  else if(spacecraftName.compare("Lunar Orbiter 5") == 0) {
    frameCode = "-535";
  }

  if(instrumentID == "High Resolution Camera") {
    frameCode += "001";
  }
  else if(instrumentID == "Medium Resolution Camera") {
    frameCode += "002";
  }

  //Create subframe and frame keywords
  QString imgNumber = (QString) inst.findKeyword("ImageNumber");
  int subFrame = toInt(imgNumber.mid(5));

  inst.addKeyword(PvlKeyword("SubFrame", toString(subFrame)));
  //ImageNumber is auto translated, and no longer needed
  inst.deleteKeyword("ImageNumber");

  kerns += PvlKeyword("NaifFrameCode", frameCode);
  outputLabel->findObject("IsisCube").addGroup(kerns);

  return;
}
