
#include "vlkb_ast.hpp"

#include "ast4vl.hpp" // cout operator needed
#include "cutout.hpp" // coordinates needed
#include "cutout_ostream.hpp"
#include "service_string.hpp"
#include "fitsfiles.hpp" // header-string needed

#include "io.hpp"
#include "my_assert.hpp"

#include <iostream>
#include <climits> // INT_MAX needed
#include <sstream>
#include <vector>


using namespace std;




//---------------------------------------------------------------------
// vertices
//---------------------------------------------------------------------

int vlkb_skyvertices(const string& pathname, const string& skysys_str)
{
   LOG_trace(__func__);

   int maxHdu = 1;// FIXMEINT_MAX; // read all HDU's

   std::vector<fitsfiles::Hdu> allHdus = 
      fitsfiles::fname2hdrstr(pathname, maxHdu);

   for(unsigned int i=0; i<allHdus.size(); i++)
   {
      cout << "HDU#" << i << endl;

      fitsfiles::Hdu hd = allHdus.at(i);

      vector<point2d> vertices = calc_skyvertices(hd.m_header, skysys_str);

      for(point2d vertex : vertices) cout << " " << vertex << endl;
   }

   return 0;
}



//---------------------------------------------------------------------
// bounds
//---------------------------------------------------------------------
/*
const string VELOLSRK{"System=VELO,StdOfRest=LSRK,Unit=km/s"};
const string WAVEBARY{"System=WAVE,StdOfRest=Bary,Unit=m"};
*/
int vlkb_listbounds(const string& skysys_str, const string& specsys_str, const string& pathname)
{
   LOG_trace(__func__);

   int maxHdu = 1;//FIXME INT_MAX; // read all HDU's

   std::vector<fitsfiles::Hdu> allHdus = 
      fitsfiles::fname2hdrstr(pathname, maxHdu);

   for(unsigned int i=0; i<allHdus.size(); i++)
   {
      cout << "HDU#" << i << endl;

      fitsfiles::Hdu hd = allHdus.at(i);

      vector<Bounds> bounds_vec = calc_bounds(hd.m_header, skysys_str, specsys_str);

      for(Bounds bnds : bounds_vec) cout << bnds << endl;
   }

   return 0;
}









//---------------------------------------------------------------------
// overlap with area given in query-string form (name=value&...)
//---------------------------------------------------------------------

// parse query string to service::coordinates

vector<string> split (const string &s, char delim)
{
   vector<string> result;
   stringstream ss (s);
   string item;

   while (getline (ss, item, delim)) {
      result.push_back (item);
   }

   return result;
}

coordinates parse_coordinates(const string query_string)
{
   LOG_trace(__func__);

   coordinates coord;
   coord.specsys = specsystem::NONE;

   vector<string> params = split(query_string, '&');

   for(string param : params)
   {
      vector<string> pair = split(param, '=');

      my_assert(pair.size() == 2, __FILE__,__LINE__, "one '=' sign expected in '" + param + "'");

      string name  = pair[0];
      string value = pair[1];

      if(name.empty() || value.empty()) continue;

      /* FIXME what are inited values of coord if param not given in the query string */
      if(name.compare("skysystem") == 0) coord.skysys = to_skysystem(value);
      else if(name.compare("l") == 0)    coord.lon_deg = stod(value);
      else if(name.compare("b") == 0)    coord.lat_deg = stod(value);
      else if(name.compare("dl") == 0)   {coord.shape = area::RECT; coord.dlon_deg = stod(value);}
      else if(name.compare("db") == 0)   {coord.shape = area::RECT; coord.dlat_deg = stod(value);}
      else if(name.compare("r") == 0)    {coord.shape = area::CIRCLE; coord.dlon_deg = coord.dlat_deg = 2.0 * stod(value);}
      else if(name.compare("specsystem") == 0) coord.specsys = to_specsystem(stoi(value));
      else if(name.compare("vl") == 0)   coord.vl_kmps = stod(value);
      else if(name.compare("vu") == 0)   coord.vu_kmps = stod(value);
   }

   return coord;
}


int vlkb_overlap(const string& pathname, const string& region)
{
   LOG_trace(__func__);

   int maxHdu = 1;// INT_MAX; FIXME fitsfiles::header throws error reading behind end-of-file due to INT_MAX 

   std::vector<fitsfiles::Hdu> allHdus = 
      fitsfiles::fname2hdrstr(pathname, maxHdu);

   //cout << region << endl;

   const coordinates coord = parse_coordinates(region.c_str());
   //cout << coord << endl;

   int rc = -1; // FIXME only last ov_code will be returned from the cycle
   for(unsigned int i=0; i<allHdus.size(); i++)
   {
      //cout << "HDU#" << i << endl;

      fitsfiles::Hdu hd = allHdus.at(i);

      vector<uint_bounds> bnds = calc_overlap(hd.m_header, coord, rc);
      cout << to_cfitsio_format(bnds) << endl;

      //for(uint_bounds bnd : bnds) cout << bnd << endl;
   }

   return rc;
}


