#pragma once

#include <iostream>
#include <string>
#include <stdlib.h>
#include <taos.h>
#include <list>

using namespace std;

list<list<string>> reading();
bool Readtxt(string txtname, list<string>& output);
long* GetFitsAxes(string filename);

/*
	Regresamos una lista de listas con el siguiente orden: Bias, Darks, Flats, FitsFiles.
	La lista de Bias, Darks o Flats pueden ser vacias, pero no FitsFiles.
*/
list<list<string>> reading() {

	//Lista que regresaremos
	list<list<string>> rlist;

#pragma region Lectura de fits txt
	//Lectura de archivos de texto
	list<string> FitsFileList;

	//Leemos archivo(s) fits del txt
	if (!Readtxt(FITS_TXT, FitsFileList)) {
		std::cout << "Error al abrir archivo " << FITS_TXT << std::endl;
		exit(EXIT_FAILURE);
	}
	else if (FitsFileList.size() <= 0) {
		std::cout << "No hay ningun archivo fits por leer " << std::endl;
		exit(EXIT_FAILURE);
	}
#pragma endregion

#pragma region Lectura Bias, Darks, Flats txt
	list<string> Biastxt;
	list<string> Darkstxt;
	list<string> Flatstxt;
	bool bbias = false;
	bool bdarks = false;
	bool bflats = false;

	//Leemos archivo bias del txt
	if (!Readtxt(BIAS_TXT, Biastxt)) {
		std::cout << "Error al abrir archivo " << BIAS_TXT << std::endl;
		exit(EXIT_FAILURE);
	}
	else if (Biastxt.size() <= 0) {
		bbias = false;
	}
	else {
		bbias = true;
	}
	//Leemos archivo darks del txt
	if (!Readtxt(DARKS_TXT, Darkstxt)) {
		std::cout << "Error al abrir archivo " << DARKS_TXT << std::endl;
		exit(EXIT_FAILURE);
	}
	else if (Darkstxt.size() <= 0) {
		bdarks = false;
	}
	else {
		bdarks = true;
	}
	//Leemos archivo flats del txt
	if (!Readtxt(FLATS_TXT, Flatstxt)) {
		std::cout << "Error al abrir archivo " << FLATS_TXT << std::endl;
		exit(EXIT_FAILURE);
	}
	else if (Flatstxt.size() <= 0) {
		bflats = false;
	}
	else {
		bflats = true;
	}
#pragma endregion

#pragma region revision
	string file;
	long* axes;
	int xs;
	int ys;
	int frames;
	int last_xs, last_ys;
	int i = 0;
	bool check = true;

	for (list<string>::iterator itr = FitsFileList.begin(); itr != FitsFileList.end(); itr++) {
		file = *itr;
		axes = GetFitsAxes(FITS_FILE_PATH + file);
		xs = axes[0];
		ys = axes[1];
		frames = axes[2];

		if (i > 0) {
			if (last_xs != xs || last_ys != ys) {
				check = false;
				break;
			}
		}

		last_xs = xs;
		last_ys = ys;
		i++;
	}

	if (!check) {
		std::cout << "El archivo (" << i << ") " << file << " no coincide en sus ejes" << std::endl;
		exit(EXIT_FAILURE);
	}

	if (bbias) {
		file = *Biastxt.begin();
		axes = GetFitsAxes(FITS_FILE_PATH + file);
		xs = axes[0];
		ys = axes[1];

		if (last_xs != xs || last_ys != ys) {
			std::cout << "Los ejes del archivo Bias: " << file << " no coincide en sus ejes" << std::endl;
			exit(EXIT_FAILURE);
		}
		else {
			rlist.push_back(Biastxt);
		}
	}
	else {
		rlist.push_back(list<string>());
	}
	if (bdarks) {
		file = *Darkstxt.begin();
		axes = GetFitsAxes(FITS_FILE_PATH + file);
		xs = axes[0];
		ys = axes[1];

		if (last_xs != xs || last_ys != ys) {
			std::cout << "Los ejes del archivo Darks: " << file << " no coincide en sus ejes" << std::endl;
			exit(EXIT_FAILURE);
		}
		else {
			rlist.push_back(Darkstxt);
		}
	}
	else {
		rlist.push_back(list<string>());
	}
	if (bflats) {
		file = *Flatstxt.begin();
		axes = GetFitsAxes(FITS_FILE_PATH + file);
		xs = axes[0];
		ys = axes[1];

		if (last_xs != xs || last_ys != ys) {
			std::cout << "Los ejes del archivo Flats: " << file << " no coincide en sus ejes" << std::endl;
			exit(EXIT_FAILURE);
		}
		else {
			rlist.push_back(Flatstxt);
		}
	}
	else {
		rlist.push_back(list<string>());
	}
#pragma endregion

	rlist.push_back(FitsFileList);

	return rlist;
}

/*
	Leemos un archivo txt en FILE_PATH con nombre txtname;
	nos devuelve una lista de strings de cada renglon en el archivo
*/
bool Readtxt(string txtname, list<string>& output) {

	ifstream txt;
	string str;

	txt.open(string(FILE_PATH + txtname).c_str());

	if (txt.is_open()) {
		while (!txt.eof()) {

			txt >> str;

			if (str != "") {
				output.push_back(str);
			}

			str = string();

		}
	}
	else {
		return false;
	}

	return true;

}

/*
	Devuelve el valor de los ejes X, Y, Z del cubo de datos "filename"
	axes[0] = X
	axes[1] = Y
	axes[2] = Z (Frames)
*/
long* GetFitsAxes(string filename) {

	fitsfile* fptr;
	int status = 0;
	long naxes[3];
	int nfound;

	//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, 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, status);
		exit(EXIT_FAILURE);
	}

	//Cerramos el archivo
	if (fits_close_file(fptr, &status)) {
		fits_report_error(stderr, status);
		exit(EXIT_FAILURE);
	}

	delete file;

	return naxes;
}
