#include <list>
#include <iostream>
#include "Calibration.h"

using namespace std;

Calibration::Calibration() {

}

Calibration::Calibration(string name):SourceFits(name) {
	
}

Calibration::~Calibration() {
	if (data) {
		std::cout << "Liberando memoria de data en Calibration file " << filename << "\n";
		free(data);
		data = NULL;
		std::cout << "Done \n";
	}
}

void Calibration::ObtainMaster() {

}

long Calibration::getMedian(list<long> l) {
	long mitad = l.size() / 2;
	long media;

	list<long>::iterator itr = l.begin();

	if (l.size() % 2 == 0) {

		//Si el tamaņo de la lista es par
		std::advance(itr, mitad - 1);
		long num1 = *itr;
		itr = l.begin();
		std::advance(itr, mitad);
		long num2 = *itr;

		media = (num1 + num2) / 2;
	}
	else {

		//Si el tamaņo de la lista es impar
		std::advance(itr, mitad - 1);
		media = *itr;
	}

	return media;
}

void Calibration::setNewFile(string newfile) {
	filename = newfile;
	if (data) {
		free(data);
		data = NULL;
	}

	Xs = 0;
	Ys = 0;
	Frames = 0;
}

void Calibration::Init() {
	//Conversion de string a char[] para funcion de fits_open_file
	char* file = new char[filename.size() + 1];
	filename.copy(file, filename.size() + 1);
	file[filename.size()] = '\0';

	//Abrimos el archivo
	if (fits_open_file(&fptr, file, READONLY, &status)) {
		fits_report_error(stderr, this->status); //Imprime error de status
		exit(EXIT_FAILURE);
	}

	//Ancho y Largo de la imagen en pixeles
	if (fits_read_keys_lng(fptr, "NAXIS", 1, 3, naxes, &nfound, &status)) {
		fits_report_error(stderr, this->status); //Imprime error de status
		exit(EXIT_FAILURE);
	}

	Xs = naxes[0];
	Ys = naxes[1];
	Frames = naxes[2];

	FitsReadFile();

	//Cerramos el archivo
	if (fits_close_file(fptr, &status)) {
		fits_report_error(stderr, this->status); //Imprime error de status
		exit(EXIT_FAILURE);
	}

	delete []file;
}

void Calibration::FitsReadFile() {
	//Leemos todo el archivo imagen, se debe obtener un vector con datos

	//Declaramos desde donde queremos comenzar a leer la imagen en fpixel:
	long fpixel[] = { 1, 1, 1 };

	//Debemos obtener el total de pixeles que contiene la imagen y la cantidad de frames del archivo
	long int nelements = Xs;	//Pixeles a leer por renglon

	//Tamaņo del arreglo donde se guardaran los datos:
	//data = (long int*)calloc(Xs * Ys * Frames, sizeof(long int));
	data = (long int*)calloc(Xs * Ys * Frames, sizeof(long int));
	long int* tempdata = (long int*)calloc(nelements, sizeof(long int));

	//nulval se de clara como short -1 y anynul se trabaja con un int 0, datatype para leer TULONG
	short nulval = -1;

	int frame, row;
	int XYs = Xs * Ys;

	if (Frames > 0) {

		//Recorremos cada frame
		for (int i = 0; i < naxes[2]; i++)
		{

			fpixel[2] = i + 1;
			frame = i;

			//Recorremos cada renglon
			for (int j = 0; j < nelements; j++)
			{
				fpixel[1] = j + 1;
				row = j;

				if (fits_read_pix(this->fptr, TLONG, fpixel, nelements, &nulval, tempdata, 0, &this->status)) {
					fits_report_error(stderr, this->status); //Imprime error de status
					exit(EXIT_FAILURE);
				}

				for (int k = 0; k < nelements; k++)
				{
					data[(frame * XYs) + (row * nelements) + k] = tempdata[k];
				}
			}
		}
	}
	else {

		fpixel[2] = 1;

		//Recorremos cada renglon
		for (int j = 0; j < Ys; j++)
		{
			fpixel[1] = j + 1;
			row = j;

			if (fits_read_pix(this->fptr, TLONG, fpixel, nelements, &nulval, tempdata, 0, &this->status)) {
				fits_report_error(stderr, this->status); //Imprime error de status
				exit(EXIT_FAILURE);
			}

			for (int k = 0; k < nelements; k++)
			{
				data[(row * nelements) + k] = tempdata[k];
			}
		}
	}

	free(tempdata);
}