#pragma once

//#include <cstring>
#include <string.h>
#include "MPT_Exception.h"

namespace MobilePhotoTool{

	/**
	 * 
	 * @author uwe
	 * @version 1
	 * 
	 * IFD_TYPE class saves the type and tag of the IFD ENTRY. 
	 * If the IFD ENTRY is not known by the reader the constructor throws a exception.
	 * If the Tag and Type of value do not match the constructor throws a exception.
	 */
	class IFD_TYPE
	{
	public:
		static const int IN_BYTE 		=	1;
		static const int IN_ASCII		=	2;
		static const int IN_SHORT		=	3;
		static const int IN_LONG		=	4;
		static const int IN_RATIONAL	=	5;
		static const int IN_SBYTE		=	6;
		static const int IN_UNDEFINED	=	7;
		static const int IN_SSHORT		=	8;
		static const int IN_SLONG		=	9;
		static const int IN_SRATIONAL	=  10;
		static const int IN_FLOAT		=  11;
		static const int IN_DOUBLE		=  12;
		static const int IN_IFD			=  13;
	
		static const int ID_BYTE 		=	0x0001;
		static const int ID_ASCII		=	0x0002;
		static const int ID_SHORT		=	0x0004;
		static const int ID_LONG		=	0x0008;
		static const int ID_RATIONAL	=	0x0010;
		static const int ID_SBYTE		=	0x0020;
		static const int ID_UNDEFINED	=	0x0040;
		static const int ID_SSHORT		=	0x0080;
		static const int ID_SLONG		=	0x0100;
		static const int ID_SRATIONAL	=	0x0200;
		static const int ID_FLOAT		=	0x0400;
		static const int ID_DOUBLE		=	0x0800;
		static const int ID_IFD			=	0x1000;
	
		static const int NewSubfileType 			=   254;
		static const int ImageWidth					=   256;
		static const int ImageLength				=   257;
		static const int BitsPerSample				=   258;
		static const int Compression				=   259;
		static const int PhotometricInterpretation	=	262;
		static const int Make						=	271;
		static const int Model						=	272;
		static const int StripOffsets				=	273;
		static const int Orientation				=	274;
		static const int SamplesPerPixel			=	277;
		static const int RowsPerStrip				=	278;
		static const int StripByteCounts			=	279;
		static const int XResolution				=	282;
		static const int YResolution				=	283;
		static const int PlanarConfiguration		=	284;
		static const int ResolutionUnit				=	296;
		static const int Software					=	305;
		static const int DateTime					=	306;
		static const int WhitePoint					=	318;
		static const int PrimaryChromaticities		=	319;
		static const int SubIFDs					=	330;
		static const int YCbCrCoefficients			=	529;
		static const int YCbCrSubSampling			=	530;
		static const int YCbCrPositioning			=	531;
		static const int Exif_IFD					= 34665;
		static const int DNGVersion					= 50706;
		static const int DNGBackwardVersion			= 50707;
		static const int UniqueCameraModel			= 50708;
		static const int ColorMatrix1				= 50721;
		static const int ColorMatrix2				= 50722;
		static const int AnalogBalance				= 50727;
		static const int AsShotNeutral				= 50728;
		static const int BaselineExposure			= 50730;
		static const int BaselineNoise				= 50731;
		static const int BaselineSharpness			= 50732;
		static const int LinearResponseLimit		= 50734;
		static const int DNGPrivateData				= 50740;
		static const int CalibrationIlluminant1		= 50778;
		static const int CalibrationIlluminant2		= 50779;
	
		static const int CFARepeatPatternDim		= 33421;
		static const int CFAPattern					= 33422;
		static const int CFALayout					= 50711;
		static const int BlackLevelRepeatDim		= 50713;
		static const int BlackLevel					= 50714;
		static const int WhiteLevel					= 50717;
		static const int DefaultScale				= 50718;
		static const int DefaultCropOrigin			= 50719;
		static const int DefaultCropSize			= 50720;
		static const int BayerGreenSplit			= 50733;
		static const int AntiAliasStrength			= 50738;

		static const IFD_TYPE *IFD_TYPE_KNOWN[];
		
		int TAG;
		int IN_TYPE;

	private:
		
		int 			ID_TYPE;
		const IFD_TYPE *known_type;
		char  			*description;

	public:
		/**
		 * Stores tag and type of the IFD ENTRY.
		 * 
		 * @param TAG The tag of the IFD ENTRY.
		 * @param IN_TYPE The type of the IFD ENTRY.
		 * @throws Exception If the tag or the type is not known or tag and type does not match this exception will be thrown.
		 */
		IFD_TYPE(MPT_Exception *exception, int TAG, int IN_TYPE);

		~IFD_TYPE(void);

		/**
		 * Returns the length of this type in bytes for Byte it returns 1, for Long
		 * it returns 4 and so on.
		 *
		 * @return number of bytes.
		 */
		int type_length(MPT_Exception *exception);

	private:
		IFD_TYPE(const int TAG, const int ID_TYPE, const char *description);
		static const IFD_TYPE *get_IFD_TYPE_KNOWN(MPT_Exception *exception, int TAG);
		static int IN_TYPE_to_ID_TYPE(MPT_Exception *exception, int IN_TYPE);

	};
}
