
#include "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;
}




//---------------------------------------------------------------------
// header backup and modif
//---------------------------------------------------------------------
/*
const string VELOLSRK{"System=VELO,StdOfRest=LSRK,Unit=km/s"};
const string WAVEBARY{"System=WAVE,StdOfRest=Bary,Unit=m"};
*/

void write_previous(string header, string filename)
{
   std::ofstream out(filename);
   out << header;
}

void read_lines(string pathname, vector<string>& lines)
{
	LOG_trace(__func__);

	static const string empty_card{"                                                                                "};

	lines.clear();
	ifstream file(pathname);
	string s;
	while (getline(file, s))
	{
		if(s.size()<80) s += empty_card.substr(0, 80-s.size());
		lines.push_back(s);
	}
}

int header_backup(const string& pathname, int extnum, const string& extra_cards_pathname, bool backup, std::ostream& ostrm)
{
	LOG_trace(__func__);

   LOG_STREAM << pathname << " " << extnum << endl;

	vector<string> extra_cards;
	read_lines(extra_cards_pathname, extra_cards);

	int maxHdu = extnum+1;
	int minHdu = extnum+1;
	std::vector<fitsfiles::Hdu> allHdus =
		fitsfiles::fname2hdrstr(pathname, extra_cards, maxHdu, minHdu);

	for(unsigned int i=0; i<allHdus.size(); i++)
	{
		fitsfiles::Hdu hd = allHdus.at(i);

		if(backup)
			write_previous(hd.m_header, pathname +"hdr" + ((i>0) ? "#" + to_string(i+1)  : "") );
		else
		{
			unsigned long ii = 0;
			unsigned long hdr_len = hd.m_header.length();
         LOG_STREAM << "header card count: " << hdr_len/80 << endl;
			while((ii*80+80) <= hdr_len)
			{
				ostrm << hd.m_header.substr(80*ii++, 80) << 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;
}

void update_with_pixel_i(vector<uint_bounds>& bnds, vector<uint_bounds> pix_vec)
{
	for(unsigned int i=0; ( i<pix_vec.size() ) && ( i<bnds.size() ); i++)
		if(pix_vec[i].type == 'x') bnds[i] = pix_vec[i];
}

int vlkb_overlap(const string& pathname, const string& region, vector<uint_bounds>& bnds) 
{
	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);

	const coordinates coord = parse_coordinates(region.c_str());

	int ov_code;
	for(unsigned int i=0; i<allHdus.size(); i++)
	{
		fitsfiles::Hdu hd = allHdus.at(i);
		bnds = calc_overlap(hd.m_header, coord, ov_code);
	}
   update_with_pixel_i(bnds, coord.pixel_i);
	return ov_code;
}


