
// convert parameters to/from JSON and call vlkb services

// NOTE merge_id
// jobId exists if we run under UWS (MERGE1,2,3)
// create merge-id = amqp-queuename + jobId 
// such id is uniq when running MERGE parallel and more deploys
// of vlkb-dtasets present against the same amqp-broker

#include "json_service_call.hpp"
#include "config.hpp"
#include "io.hpp"
#include "cutout.hpp"
#include "cutout_nljson.hpp"
#include "mcutout.hpp"
#include "mcutout_nljson.hpp"
#include "json_request.hpp"
#include "json_reply.hpp"

#include "fitsfiles.hpp" // calc_nullvals

#include <stdexcept>
#include <vector>
#include <string>


using namespace std;


string to_string(service_error serr)
{
   string str;
   switch(serr)
   {
      case service_error::INVALID_PARAM: return "INVALID_PARAM"; break;
      case service_error::SYSTEM_ERROR:  return "SYSTEM_ERROR"; break;
   }

   LOG_STREAM << string(__FILE__) << ":" << to_string(__LINE__) << "unrecognized value in service_error type" << endl;

   return str;
}



string service_exception(service_error error, const string what)
{
   LOG_trace(__func__);

   json jreply;

   switch(error)
   {
      case service_error::INVALID_PARAM:
         jreply["exception"] = { {"type","INVALID_PARAM"}, {"msg",what} };
         break;
      case service_error::SYSTEM_ERROR:
         jreply["exception"] = { {"type","SYSTEM_ERROR"}, {"msg",what} };
         break;
   }

   LOG_STREAM << to_string(error) + ": " + what << endl;

   return jreply.dump();
}



string service_call(string request_json, string queuename, config conf)
{
   LOG_trace(__func__);

   const string setts_fitsdir{conf.getFitsDir()};
   const string setts_fitscutdir{conf.getFitsCutDir()};

   LOG_STREAM << request_json << endl;

   json_request req(request_json);

   json_reply reply;

   if(req.is_subimg())
   {
      cutout_res_s cutres = do_cutout_file(
            req.img_pathname(), req.img_hdunum(),
            req.get_pos(), req.get_band(), req.get_time(), req.get_pol(),
            req.count_null_values(),
            req.extra_cards(),
            setts_fitsdir,
            setts_fitscutdir);

      reply.put_cutout_result(cutres);
   }
   else if(req.is_mcutout())
   {
      struct mcutout_res_s mres = mcutout(req.cut_params(), setts_fitsdir, setts_fitscutdir);

      mres.tgz_filename = setts_fitscutdir + "/" + mres.tgz_filename;
      mres.filesize     = fitsfiles::fileSize(mres.tgz_filename);
      reply.put_mcutout_result(mres);
   }
   else if(req.is_mergefiles())
   {
      string mergedfile_pathname;

      unsigned long fsize = xmergefiles(
            req.files_to_merge(),
            req.dimensionality(),
            setts_fitscutdir, setts_fitscutdir,
            mergedfile_pathname);

      cutout_res_s cutres{ fsize, mergedfile_pathname, {-1.0, 0, 0} };
      reply.put_cutout_result(cutres);
   }
   else if(req.is_mergefiles_common_header())
   {
      string merge_id(queuename + "_" + req.merge_id());

      xmergefiles_common_header(
            merge_id,
            req.files_to_merge(),
            req.dimensionality(),//FIXME convert to int: dimensionslity
            setts_fitscutdir, setts_fitscutdir);
   }
   else if(req.is_mergefiles_reproject())
   {
      string merge_id(queuename + "_" + req.merge_id());

      xmergefiles_reproject(
            merge_id,
            req.fitsfilename(),
            req.dimensionality(),//FIXME convert to int: dimensionslity
            setts_fitscutdir, setts_fitscutdir);
   }
   else if(req.is_mergefiles_add_reprojected())
   {
      string merge_id(queuename + "_" + req.merge_id());

      string mergedfile_pathname;

      unsigned long fsize = xmergefiles_add_reprojected(
            merge_id,
            req.dimensionality(),
            setts_fitscutdir, setts_fitscutdir,
            mergedfile_pathname);

      cutout_res_s cutres{ fsize, mergedfile_pathname, {-1.0, 0, 0} };
      reply.put_cutout_result(cutres);
   }
   else
   {
      throw std::runtime_error("unrecognized vlkb service");
   }

   return reply.json_str();
}



