#pragma once

#include "MPT_Buffer.h"
#include "MobilePhoteTool_IFD.h"
#include "Raw_Processor_Creater.h"
#include "Mathe.h"
#include "MPT_Exception.h"
#include "IFD_TYPE.h"
//#include <vector>
using namespace std;

namespace MobilePhotoTool{
	class TIFF_reader
	{


	private:
		/**
		 * The inputbuffer
		 */
		MPT_Buffer *buffer;

		/**
		 * Read the structur of the inputfile
		 */
		void read_Header(MPT_Exception *exception);

		/**
		 * The IFD in this tiff file
		 */
		IFD **ifd;

		/**
		 * The number of ifds
		 */
		size_t number_ifd;


		/**
		 * This ifd points to the preview
		 */
		IFD *ifd_preview;

		/**
		 * This ifd points to the exif
		 */
		IFD *ifd_exif;

		/**
		 * Search for the preview ifd and saves it in this->ifd_preview.
		 * 
		 */
		void set_ifd_preview(MPT_Exception *exception);

		/**
		 * The maximal number of Pixel
		 */
		static const unsigned int MAX_PIXEL = 100000000;

		/**
		 * The class for all raw processing,
		 */
		Raw_Processor *raw_processor;

		/**
		 *
		 */
		void load_Raw_Processor(MPT_Exception *exception);

		/**
		 * The main exception
		 */
		MPT_Exception *exception;


		/**
		 * Add a new ifd to the reader;
		 */
		void set_IFD(MPT_Exception *exception, IFD *ifd);


		/**
		 * Opens the exif information.
		 * Return 0 by success
		 */
		unsigned int set_Exif(MPT_Exception *exception);

	public:

		/**
		 * Constructs a TIFF_reader 
		 *
		 * @param path The path to a valid tiff or dng file.
		 */
		TIFF_reader(MPT_Exception *exception, const char *path);

		~TIFF_reader(void);

		/**
		 *	@return The preview image width.
		 */
		unsigned int get_preview_width(MPT_Exception *exception);

		/**
		 *	@return The preview image length.
		 */
		unsigned int get_preview_length(MPT_Exception *exception);


		/**
		 * The data array will filled with the preview image.
		 * Take care, that data is big enough.
		 *
		 * @param data Here the image will be saved.
		 * @param size The maximum size of integer fits in data
		 * @return If the function works it will be 0.
		 */
		unsigned int getPreview_int_RGB(MPT_Exception *exception, unsigned int *data, size_t size);

		/**
		 * The data array will filled with the preview image.
		 * Take care, that data is big enough.
		 *
		 * @param data Here the image will be saved.
		 * @param size The maximum size of integer fits in data
		 * @return If the function works it will be 0.
		 */
		unsigned int getPreview_int_RGB(MPT_Exception *exception, unsigned short *data, size_t size);

		/**
		 * Get the current Raw_Processor. If there ara no Raw_Processor it
		 * create one.
		 */
		Raw_Processor *get_Raw_Processor(MPT_Exception *exception);

		/**
		 *
		 */
		MPT_Exception *get_exception();

		/**
		 *
		 */
		unsigned int get_Exif_byte_size(MPT_Exception *exception);

		/**
		 * Extract from the Exif the Exposure Time and write the time as rationel in the retrun_value.
		 * If there is no Exif_ExposureTime it return 0;
		 */
		unsigned int get_Exif_ExposureTime(MPT_Exception *exception, unsigned int return_value[2]);

		unsigned int get_Exif_FNumber(MPT_Exception *exception, unsigned int return_value[2]);

		unsigned int get_Exif_ExposureProgram(MPT_Exception *exception, unsigned int retru_value[1]);

		unsigned int get_Exif_ISOSpeedRatings(MPT_Exception *exception, unsigned int retru_value[1]);

		unsigned int get_Exif_DateTimeOriginal(MPT_Exception *exception, char retru_value[20]);

		unsigned int get_Exif_SubsecTimeOriginal(MPT_Exception *exception, char retru_value[20]);

		unsigned int get_Exif_DateTimeDigitized(MPT_Exception *exception, char retru_value[20]);

		unsigned int get_Exif_SubsecTimeDigitized(MPT_Exception *exception, char retru_value[20]);

		unsigned int get_Exif_ExposureBiasValue(MPT_Exception *exception, int retru_value[2]);

		unsigned int get_Exif_MeteringMode(MPT_Exception *exception, unsigned int retru_value[1]);

		unsigned int get_Exif_Flash(MPT_Exception *exception, unsigned int retru_value[1]);

		unsigned int get_Exif_FlashEnergy(MPT_Exception *exception, unsigned int retru_value[2]);

		unsigned int get_Exif_FocalLength(MPT_Exception *exception, unsigned int retru_value[2]);

		unsigned int get_Exif_FocalLengthIn35mmFilm(MPT_Exception *exception, unsigned int retru_value[1]);

		unsigned int get_Exif_SensingMethod(MPT_Exception *exception, unsigned int retru_value[1]);

		unsigned int get_Exif_CustomRendered(MPT_Exception *exception, unsigned int retru_value[1]);

		unsigned int get_Exif_ExposureMode(MPT_Exception *exception, unsigned int retru_value[1]);

		unsigned int get_Exif_WhiteBalance(MPT_Exception *exception, unsigned int retru_value[1]);

		unsigned int get_Exif_SceneCaptureType(MPT_Exception *exception, unsigned int retru_value[1]);

		unsigned int get_Exif_Contrast(MPT_Exception *exception, unsigned int retru_value[1]);

		unsigned int get_Exif_Saturation(MPT_Exception *exception, unsigned int retru_value[1]);

		unsigned int get_Exif_Sharpness(MPT_Exception *exception, unsigned int retru_value[1]);

		unsigned int get_Exif_BaselineSharpness(MPT_Exception *exception, unsigned int retru_value[1]);

		unsigned int get_Exif_SubjectDistanceRange(MPT_Exception *exception, unsigned int retru_value[1]);

		static bool test_width_length(MPT_Exception *exception, unsigned int width, unsigned int length);
	};
}
