
#include "IFD_TYPE.h"

namespace MobilePhotoTool{
	

	const IFD_TYPE *IFD_TYPE::IFD_TYPE_KNOWN[] = {
		new IFD_TYPE( NewSubfileType				, ID_LONG 							,"NewSubfileType"),
		new IFD_TYPE( ImageWidth					, ID_LONG | ID_SHORT 				,"ImageWidth"),
		new IFD_TYPE( ImageLength					, ID_LONG | ID_SHORT 				,"ImageLength"),
		new IFD_TYPE( BitsPerSample					, ID_SHORT 							,"BitsPerSample"),
		new IFD_TYPE( Compression					, ID_SHORT 							,"Compression"),
		new IFD_TYPE( PhotometricInterpretation		, ID_SHORT 							,"PhotometricInterpretation"),
		new IFD_TYPE( Make							, ID_ASCII 							,"Make"),
		new IFD_TYPE( Model							, ID_ASCII 							,"Model"),
		new IFD_TYPE( StripOffsets					, ID_LONG | ID_SHORT 				,"StripOffsets"),
		new IFD_TYPE( Orientation					, ID_SHORT 							,"Orientation"),
		new IFD_TYPE( SamplesPerPixel				, ID_SHORT 							,"SamplesPerPixel"),
		new IFD_TYPE( RowsPerStrip					, ID_LONG | ID_SHORT 				,"RowsPerStrip"),
		new IFD_TYPE( StripByteCounts				, ID_LONG | ID_SHORT 				,"StripByteCounts"),
		new IFD_TYPE( XResolution					, ID_RATIONAL		 				,"XResolution"),
		new IFD_TYPE( YResolution					, ID_RATIONAL 						,"YResolution"),
		new IFD_TYPE( PlanarConfiguration			, ID_SHORT 							,"PlanarConfiguration"),
		new IFD_TYPE( ResolutionUnit				, ID_SHORT 							,"ResolutionUnit"),
		new IFD_TYPE( Software						, ID_ASCII			 				,"Software"),
		new IFD_TYPE( DateTime						, ID_ASCII			 				,"DateTime"),
		new IFD_TYPE( SubIFDs						, ID_LONG | ID_IFD 					,"SubIFDs"),
		new IFD_TYPE( Exif_IFD						, ID_LONG 							,"Exif IFD"),
		new IFD_TYPE( DNGVersion					, ID_BYTE			 				,"DNGVersion"),
		new IFD_TYPE( DNGBackwardVersion			, ID_BYTE							,"DNGBackwardVersion"),
		new IFD_TYPE( UniqueCameraModel				, ID_ASCII							,"UniqueCameraModel"),
		new IFD_TYPE( ColorMatrix1					, ID_SRATIONAL		 				,"ColorMatrix1"),
		new IFD_TYPE( ColorMatrix2					, ID_SRATIONAL		 				,"ColorMatrix2"),
		new IFD_TYPE( AnalogBalance					, ID_RATIONAL		 				,"AnalogBalance"),
		new IFD_TYPE( AsShotNeutral					, ID_RATIONAL | ID_SHORT 			,"AsShotNeutral"),
		new IFD_TYPE( BaselineExposure				, ID_SRATIONAL 						,"BaselineExposure"),
		new IFD_TYPE( BaselineNoise					, ID_RATIONAL						,"BaselineNoise"),
		new IFD_TYPE( BaselineSharpness				, ID_RATIONAL		 				,"BaselineSharpness"),
		new IFD_TYPE( LinearResponseLimit			, ID_RATIONAL		 				,"LinearResponseLimit"),
		new IFD_TYPE( DNGPrivateData				, ID_BYTE							,"DNGPrivateData"),
		new IFD_TYPE( CalibrationIlluminant1		, ID_SHORT 							,"CalibrationIlluminant1"),
		new IFD_TYPE( CalibrationIlluminant2		, ID_SHORT 							,"CalibrationIlluminant2"),
		new IFD_TYPE( CFARepeatPatternDim			, ID_SHORT 							,"CFARepeatPatternDim"),
		new IFD_TYPE( CFAPattern					, ID_BYTE 							,"CFAPattern"),
		new IFD_TYPE( CFALayout						, ID_SHORT 							,"CFALayout"),
		new IFD_TYPE( BlackLevelRepeatDim			, ID_SHORT 							,"BlackLevelRepeatDim"),
		new IFD_TYPE( BlackLevel					, ID_SHORT | ID_LONG | ID_RATIONAL	,"BlackLevel"),
		new IFD_TYPE( WhiteLevel					, ID_SHORT | ID_LONG				,"WhiteLevel"),
		new IFD_TYPE( DefaultScale					, ID_RATIONAL	 					,"DefaultScale"),
		new IFD_TYPE( DefaultCropOrigin				, ID_SHORT | ID_LONG | ID_RATIONAL	,"DefaultCropOrigin"),
		new IFD_TYPE( DefaultCropSize				, ID_SHORT | ID_LONG | ID_RATIONAL	,"DefaultCropSize"),
		new IFD_TYPE( BayerGreenSplit				, ID_LONG							,"BayerGreenSplit"),
		new IFD_TYPE( AntiAliasStrength				, ID_RATIONAL						,"AntiAliasStrength"),
		new IFD_TYPE( WhitePoint					, ID_RATIONAL						,"WhitePoint"),
		new IFD_TYPE( PrimaryChromaticities			, ID_RATIONAL						,"PrimaryChromaticities"),
		new IFD_TYPE( YCbCrCoefficients				, ID_RATIONAL						,"YCbCrCoefficients"),
		new IFD_TYPE( YCbCrSubSampling				, ID_SHORT 							,"YCbCrSubSampling"),
		new IFD_TYPE( YCbCrPositioning				, ID_SHORT 							,"YCbCrPositioning"),

		new IFD_TYPE( Exif_ExposureTime				, ID_RATIONAL						,"Exif_ExposureTime"),
		new IFD_TYPE( Exif_FNumber					, ID_RATIONAL 						,"Exif_FNumber"),
		new IFD_TYPE( Exif_ExposureProgram			, ID_SHORT 							,"Exif_ExposureProgram"),
		new IFD_TYPE( Exif_ISOSpeedRatings			, ID_SHORT 							,"Exif_ISOSpeedRatings"),
		new IFD_TYPE( Exif_DateTimeOriginal			, ID_ASCII 							,"Exif_DateTimeOriginal"),
		new IFD_TYPE( Exif_SubsecTimeOriginal		, ID_ASCII 							,"Exif_SubsecTimeOriginal"),
		new IFD_TYPE( Exif_DateTimeDigitized		, ID_ASCII 							,"Exif_DateTimeDigitized"),
		new IFD_TYPE( Exif_SubsecTimeDigitized		, ID_ASCII  						,"Exif_SubsecTimeDigitized"),
		new IFD_TYPE( Exif_ExposureBiasValue		, ID_SRATIONAL  					,"Exif_ExposureBiasValue"),
		new IFD_TYPE( Exif_MeteringMode				, ID_SHORT 							,"Exif_MeteringMode"),
		new IFD_TYPE( Exif_Flash					, ID_SHORT 							,"Exif_Flash"),
		new IFD_TYPE( Exif_FlashEnergy				, ID_RATIONAL 						,"Exif_FlashEnergy"),
		new IFD_TYPE( Exif_FocalLength				, ID_RATIONAL 						,"Exif_FocalLength"),
		new IFD_TYPE( Exif_FocalLengthIn35mmFilm	, ID_SHORT 							,"Exif_FocalLengthIn35mmFilm"),
		new IFD_TYPE( Exif_SensingMethod			, ID_SHORT 							,"Exif_SensingMethod"),
		new IFD_TYPE( Exif_CustomRendered			, ID_SHORT 							,"Exif_CustomRendered"),
		new IFD_TYPE( Exif_ExposureMode				, ID_SHORT 							,"Exif_ExposureMode"),
		new IFD_TYPE( Exif_WhiteBalance				, ID_SHORT 							,"Exif_WhiteBalance"),
		new IFD_TYPE( Exif_SceneCaptureType			, ID_SHORT 							,"Exif_SceneCaptureType"),
		new IFD_TYPE( Exif_Contrast					, ID_SHORT 							,"Exif_Contrast"),
		new IFD_TYPE( Exif_Saturation				, ID_SHORT 							,"Exif_Saturation"),
		new IFD_TYPE( Exif_Sharpness				, ID_SHORT 							,"Exif_Sharpness"),
		new IFD_TYPE( Exif_BaselineSharpness		, ID_SHORT 							,"Exif_BaselineSharpness"),
		new IFD_TYPE( Exif_SubjectDistanceRange		, ID_SHORT 							,"Exif_SubjectDistanceRange"),
		new IFD_TYPE( CFALayout						, ID_SHORT 							,"CFALayout"),
		new IFD_TYPE( CFALayout						, ID_SHORT 							,"CFALayout"),
		new IFD_TYPE( CFALayout						, ID_SHORT 							,"CFALayout")
	};


	IFD_TYPE::IFD_TYPE( const int TAG, const int ID_TYPE, const char* description)
	{
		this->TAG			= TAG;
		this->ID_TYPE		= ID_TYPE;
		this->description	= new char[strlen(description) + 1];
		strcpy(this->description, description);
		this->known_type	= NULL;
	}

	IFD_TYPE::IFD_TYPE(MPT_Exception *exception, int TAG, int IN_TYPE)
	{
		const IFD_TYPE *type = IFD_TYPE::get_IFD_TYPE_KNOWN(exception, TAG);
		int id_type = IFD_TYPE::IN_TYPE_to_ID_TYPE(exception, IN_TYPE);
		MPT_EXCEPTION_TEST;

		if((type->ID_TYPE & id_type) == 0){
			MPT_EXCEPTION("TYPE and TAG do not fit together");
		}
		this->TAG 			= TAG;
		this->IN_TYPE		= IN_TYPE;
		this->ID_TYPE		= id_type;
		this->known_type	= type;
		this->description	= new char[strlen("See this.known_type") + 1];
		strcpy(this->description, "See this.known_type");
		//this->description	= str; //(char*)"See this.known_type";
	}

	IFD_TYPE::~IFD_TYPE(void)
	{
		delete []this->description;
	}


	const IFD_TYPE *IFD_TYPE::get_IFD_TYPE_KNOWN(MPT_Exception *exception, int TAG)
	{
		const IFD_TYPE *type = NULL;
		int pos;
		int length = sizeof(IFD_TYPE_KNOWN) / sizeof(IFD_TYPE *);

		for(pos = 0; pos < length; pos++){
			if(IFD_TYPE_KNOWN[pos]->TAG == TAG){
				type = IFD_TYPE_KNOWN[pos];
				break;
			}
		}
		if(type == NULL){
			MPT_EXCEPTION("Unknown TIFF Tag.") NULL;
		}
		return type;
	}

	int IFD_TYPE::IN_TYPE_to_ID_TYPE(MPT_Exception *exception,int IN_TYPE){
		int ID;
		switch(IN_TYPE){
			case IN_BYTE:
				ID = ID_BYTE;
				break;
			case IN_ASCII:
				ID = ID_ASCII;
				break;
			case IN_SHORT:
				ID = ID_SHORT;
				break;
			case IN_LONG:
				ID = ID_LONG;
				break;
			case IN_RATIONAL:
				ID = ID_RATIONAL;
				break;
			case IN_SBYTE:
				ID = ID_SBYTE;
				break;
			case IN_UNDEFINED:
				ID = ID_UNDEFINED;
				break;
			case IN_SSHORT:
				ID = ID_SSHORT;
				break;
			case IN_SLONG:
				ID = ID_SLONG;
				break;
			case IN_SRATIONAL:
				ID = ID_SRATIONAL;
				break;
			case IN_FLOAT:
				ID = ID_FLOAT;
				break;
			case IN_DOUBLE:
				ID = ID_DOUBLE;
				break;
			case IN_IFD:
				ID = ID_IFD;
				break;
			default:
				MPT_EXCEPTION("Not known TIFF type") 0;
		}
		
		return ID;
	}
	
	int IFD_TYPE::type_length(MPT_Exception *){
		int length = 0;
		switch(IN_TYPE){
			case IN_BYTE:
				length = 1;
				break;
			case IN_ASCII:
				length = 1;
				break;
			case IN_SHORT:
				length = 2;
				break;
			case IN_LONG:
				length = 4;
				break;
			case IN_RATIONAL:
				length = 8;
				break;
			case IN_SBYTE:
				length = 1;
				break;
			case IN_UNDEFINED:
				length = 1;;
				break;
			case IN_SSHORT:
				length = 2;
				break;
			case IN_SLONG:
				length = 4;
				break;
			case IN_SRATIONAL:
				length = 8;
				break;
			case IN_FLOAT:
				length = 4;
				break;
			case IN_DOUBLE:
				length = 8;
			case IN_IFD:
				length = 4;
				break;
		}	
		return length;
	}

}
