// $Header: https://oberon.oapd.inaf.it/shins/trunk/shins/src/data_mgr/fitsFileI.cpp 3652 2021-05-21 10:34:10Z depa $

#include "fitsFileI.hpp"

fitsFileI::fitsFileI(int argc, char*argv[])
{
    m_curFilenameSHINS = "";
    m_curFilenameSASHA = "";
}
fitsFileI::~fitsFileI()
{

}

Ice::Int fitsFileI::createEmptyFile(const std::string& _inFilename,
                                    const IceUtil::Optional<std::string>& _instrumentMode,
                                    std::string& _outFilename,
                                    const Ice::Current&)
{
    Ice::Int status = EXIT_SUCCESS;
    // <instrume>.<yyyymmdd>.<nnnnn>.[science | calib | monit].fits
    // try
    // {
    //     Py_Initialize();
    //     py::object main = py::import("__main__");
    //     py::object global =(main.attr("__dict__"));
    //     std::cout << "Filename of new file is " << _inFilename << std::endl;
    //     global["inFilename"] = _inFilename;
    //     global["status"] = status;
    //     global["outFilename"] = _outFilename;
    //     if (_instrumentMode)
    //       global["instrumentMode"] = _instrumentMode.get();
    //     else
    //       global["instrumentMode"] = "empty";
    //     py::object pyCreate = py::exec_file("/opt/tan/bin/create_empty_FITS.py", global);
    //     py::object pyStatus = global["status"];
    //     py::object pyOutFilename = global["outFilename"];
    //     status = py::extract<int>(pyStatus);
    //     _outFilename = py::extract<std::string>(pyOutFilename);
    //     m_curFilenameSHINS = _outFilename;
    //     I_LOG(_outFilename);
    // }
    // catch(py::error_already_set)
    // {
    //     PyErr_Print();
    //     PyErr_Clear();
    //     status = EXIT_FAILURE;
    // }
    // return status;
}


Ice::Int fitsFileI::createEmptyAndPopulateHeader(const std::string& _inFilename,
                                                 Ice::Int _bitpix,
                                                 Ice::Int _naxis,
                                                 const sharknir::SeqLong& _naxes,
                                                 const Ice::Current&)
{
  Ice::Int status = EXIT_SUCCESS;
  char* ptrFitsFilename;
  char card[81];
  char* ptrCardVal;
  fitsfile *ptrFitsFile;
  int *ptrFitsStatus = new int();
  long naxes[4] = {0,0,0,0};



  // ptrFilenameSHINS = (char* )malloc(sizeof(char) * filenameSHINS.size());

  // fits_create_file(&ptrFilenameSHINS, ptrFilenameSHINS, ptrFitsStatus);
  // free(ptrFilenameSHINS);
  // fits_create_img(ptrFilenameSHINS, bitpix, naxis, naxes, ptrFitsStatus);
  // fits_copy_data(ptrFitsFileSASHA, ptrFilenameSHINS, ptrFitsStatus);

  // fits_close_file(ptrFilenameSASHA, ptrFitsStatus);
  // fits_close_file(ptrFilenameSHINS, ptrFitsStatus);


  ptrFitsFilename = (char* )malloc(sizeof(char) * _inFilename.size());
  std::copy(_inFilename.begin(), _inFilename.end(), ptrFitsFilename);
  ptrFitsFilename[_inFilename.size()] = '\0';

  std::copy(_naxes.begin(), _naxes.end(), naxes);

  // create SHINS fits file
  // following block uses CFITSIO library and routines
  fits_create_file(&ptrFitsFile, ptrFitsFilename, ptrFitsStatus);
  free(ptrFitsFilename);

  fits_create_img(ptrFitsFile, _bitpix, _naxis, naxes, ptrFitsStatus);

  // populate header
  fits_write_key_null(ptrFitsFile,
                      "BZERO", "real = fits-value*BSCALE+BZERO",
                      ptrFitsStatus);

  fits_write_key_null(ptrFitsFile,
                      "BSCALE", "real = fits-value*BSCALE+BZERO",
                      ptrFitsStatus);


  // fits_write_key(ptrFitsFile,
  //                TSTRING, "BUNIT", "ADU", "Physical Unit of array values",
  //                ptrFitsStatus);



  fits_close_file(ptrFitsFile, ptrFitsStatus);
}

Ice::Int fitsFileI::printFITS(//const std::string& _filename,
    const std::string& _key,
    const std::string& _value,
    const IceUtil::Optional<std::string>& _comment,
    const IceUtil::Optional<std::string>& _filename,
    const Ice::Current&)
{
    Ice::Int status = EXIT_SUCCESS;
    std::string comment;
    try
    {
        Py_Initialize();
        py::object main = py::import("__main__");
        py::object global =(main.attr("__dict__"));
        py::tuple pyTupleKey;
        py::list pyLstHeader;

        if (!_comment)
            comment = "";
        else
            comment = _comment.get();

        pyTupleKey = py::make_tuple(_key, // key
                                    _value, // value
                                    comment); // comment

        if (_filename)
            global["filenameSHINS"] = _filename.get();
        else
            global["filenameSHINS"] = m_curFilenameSHINS;
        pyLstHeader.append(pyTupleKey);
        global["listFITSKewords"] = pyLstHeader;

        py::object print_obj = py::exec_file("/opt/tan/bin/print_FITS.py", global);
        py::object pyStatus = global["status"];
        status = py::extract<int>(pyStatus);
    }
    catch(py::error_already_set)
    {
        PyErr_Print();
        PyErr_Clear();
        status = EXIT_FAILURE;
    }
    return status;
}

Ice::Int fitsFileI::printFITSMultipleKeys(const sharknir::SeqString& _seqKey,
                                          const sharknir::SeqString& _seqValue,
                                          const sharknir::SeqString& _seqComment,
                                          const IceUtil::Optional<std::string>& _filename,
                                          const Ice::Current&)
{
    Ice::Int status = EXIT_SUCCESS;

    if ((_seqKey.size() == _seqValue.size()) &&
        (_seqKey.size() == _seqComment.size()))
    {
        // code for printFITSMultipleKeys ...
        try
        {
            Py_Initialize();
            py::object main = py::import("__main__");
            py::object global =(main.attr("__dict__"));
            py::tuple pyTupleKey;
            py::list pyLstHeader;

            for (unsigned int i=0; i<_seqKey.size(); i++)
            {
                pyTupleKey = py::make_tuple(_seqKey[i],    // key
                                            _seqValue[i],  // value
                                            _seqComment[i]); // comment

                pyLstHeader.append(pyTupleKey);
            }
            if (_filename)
                global["filenameSHINS"] = _filename.get();
            else
                global["filenameSHINS"] = m_curFilenameSHINS;
            global["listFITSKewords"] = pyLstHeader;
            py::object print_obj = py::exec_file("/opt/tan/bin/print_FITS.py", global);
            py::object pyStatus = global["status"];
            status = py::extract<int>(pyStatus);
        }
        catch(py::error_already_set)
        {
            PyErr_Print();
            PyErr_Clear();
            status = EXIT_FAILURE;
        }
    }
    else
    {
        E_LOG("Input sequences have different sizes");
        status = EXIT_FAILURE;
    }
    return status;
}


Ice::Int fitsFileI::mergeHeaders(const IceUtil::Optional<std::string>& _filenameSASHA,
                                 const IceUtil::Optional<std::string>& _filenameSHINS,
                                 const Ice::Current&)
{
    Ice::Int status = EXIT_SUCCESS;
    try
    {
        Py_Initialize();
        py::object main = py::import("__main__");
        py::object global =(main.attr("__dict__"));

        if (_filenameSASHA)
            global["filenameSASHA"] = _filenameSASHA.get();
        else
            global["filenameSASHA"] = m_curFilenameSASHA;
        if (_filenameSHINS)
            global["filenameSHINS"] = _filenameSHINS.get();
        else
            global["filenameSHINS"] = m_curFilenameSHINS;
        py::object print_obj = py::exec_file("/opt/tan/bin/merge_headers.py", global);
        py::object pyStatus = global["status"];
        status = py::extract<int>(pyStatus);
    }
    catch(py::error_already_set)
    {
        PyErr_Print();
        PyErr_Clear();
        status = EXIT_FAILURE;
    }
    return status;
}



Ice::Int fitsFileI::populateWithData(const IceUtil::Optional<std::string>& _filenameSASHA,
                                     const IceUtil::Optional<std::string>& _filenameSHINS,
                                     const Ice::Current&)
{
    Ice::Int status = EXIT_SUCCESS;
    try
    {
        Py_Initialize();
        py::object main = py::import("__main__");
        py::object global =(main.attr("__dict__"));

        if (_filenameSASHA)
            global["filenameSASHA"] = _filenameSASHA.get();
        else
            global["filenameSASHA"] = m_curFilenameSASHA;

        if (_filenameSHINS)
            global["filenameSHINS"] = _filenameSHINS.get();
        else
            global["filenameSHINS"] = m_curFilenameSHINS;
        py::object populate_obj = py::exec_file("/opt/tan/bin/populate_with_data.py", global);
        py::object pyStatus = global["status"];
        status = py::extract<int>(pyStatus);
    }
    catch(py::error_already_set)
    {
        PyErr_Print();
        PyErr_Clear();
        status = EXIT_FAILURE;
    }
    return status;
}

Ice::Int fitsFileI::fitsToArchive(const IceUtil::Optional<std::string>& _filenameSHINS,
                                  const Ice::Current&)
{
    Ice::Int status = EXIT_SUCCESS;
    try
    {
        Py_Initialize();
        py::object main = py::import("__main__");
        py::object global =(main.attr("__dict__"));

        if (_filenameSHINS)
            global["filenameSHINS"] = _filenameSHINS.get();
        else
            global["filenameSHINS"] = m_curFilenameSHINS;
        py::object archive_obj = py::exec_file("/opt/tan/bin/fits_to_archive.py", global);
        py::object pyStatus = global["status"];
        status = py::extract<int>(pyStatus);
    }
    catch(py::error_already_set)
    {
        PyErr_Print();
        PyErr_Clear();
        status = EXIT_FAILURE;
    }
    return status;
}


std::string fitsFileI::getCurrentFilenameSHINS(const Ice::Current&)
{
    return m_curFilenameSHINS;
}

std::string fitsFileI::getCurrentFilenameSASHA(const Ice::Current&)
{
    return m_curFilenameSASHA;
}

Ice::Int fitsFileI::setCurrentFilenameSASHA(const std::string& _filename, const Ice::Current&)
{
    m_curFilenameSASHA = _filename;
    return EXIT_SUCCESS;
}

std::string fitsFileI::saveSASHABLOB(Ice::Byte BLOBptrAddress, const IceUtil::Optional<int>& counter, const Ice::Current&)
{
  //
}
