/*****************************************************************************/
// Copyright 2006-2019 Adobe Systems Incorporated
// All Rights Reserved.
//
// NOTICE:	Adobe permits you to use, modify, and distribute this file in
// accordance with the terms of the Adobe license agreement accompanying it.
/*****************************************************************************/

/** \file
 * Class for holding top-level information about a DNG image.
 */

/*****************************************************************************/

#ifndef __dng_info__
#define __dng_info__

/*****************************************************************************/

#include "dng_auto_ptr.h"
#include "dng_classes.h"
#include "dng_errors.h"
#include "dng_exif.h"
#include "dng_ifd.h"
#include "dng_sdk_limits.h"
#include "dng_shared.h"
#include "dng_uncopyable.h"

#include <vector>

/*****************************************************************************/

/// \brief Top-level structure of DNG file with access to metadata.
///
/// See \ref spec_dng "DNG 1.1.0 specification" for information on member fields of this class.

class dng_info: private dng_uncopyable
	{
	
	public:
	
		uint64 fTIFFBlockOffset;
		
		uint64 fTIFFBlockOriginalOffset;
	
		bool fBigEndian;
		
		uint32 fMagic;
		
		AutoPtr<dng_exif> fExif;
	
		AutoPtr<dng_shared> fShared;
		
		int32 fMainIndex;
		
		int32 fMaskIndex;
  
		int32 fDepthIndex;
			
		int32 fEnhancedIndex;

		std::vector<uint32> fSemanticMaskIndices;
		
		std::vector <dng_ifd *> fIFD;

		std::vector <dng_ifd *> fChainedIFD;

		std::vector <std::vector <dng_ifd *> > fChainedSubIFD;

		AutoPtr<dng_memory_block> fXMPBlock;
		
	protected:
	
		uint32 fMakerNoteNextIFD;

		uint32 fParseDepth = 0;

	public:
	
		dng_info ();
		
		virtual ~dng_info ();

		/// Returns the number of parsed SubIFDs (including the main IFD).

		uint32 IFDCount () const
			{
			return (uint32) fIFD.size ();
			}

		/// Returns the number of chained IFDs.

		uint32 ChainedIFDCount () const
			{
			return (uint32) fChainedIFD.size ();
			}

		/// Returns number SubIFDs for a chained IFD.

		uint32 ChainedSubIFDCount (uint32 chainIndex) const
			{
			if (chainIndex >= fChainedSubIFD.size ())
				return 0;
			else
				return (uint32) fChainedSubIFD [chainIndex].size ();
			}

		/// Read dng_info from a dng_stream
		/// \param host DNG host used for progress updating, abort testing, buffer allocation, etc.
		/// \param stream Stream to read DNG data from.

		virtual void Parse (dng_host &host,
							dng_stream &stream);

		/// Must be called immediately after a successful Parse operation.

		virtual void PostParse (dng_host &host);

		/// Test validity of DNG data.
		/// \retval true if stream provided a valid DNG.

		virtual bool IsValidDNG ();
		
	protected:
		
		virtual void ValidateMagic ();

		virtual void ParseTag (dng_host &host,
							   dng_stream &stream,
							   dng_exif *exif,
							   dng_shared *shared,
							   dng_ifd *ifd,
							   uint32 parentCode,
							   uint32 tagCode,
							   uint32 tagType,
							   uint32 tagCount,
							   uint64 tagOffset,
							   int64 offsetDelta);

		virtual bool ValidateIFD (dng_stream &stream,
								  uint64 ifdOffset,
								  int64 offsetDelta);

		virtual void ParseIFD (dng_host &host,
							   dng_stream &stream,
							   dng_exif *exif,
							   dng_shared *shared,
							   dng_ifd *ifd,
							   uint64 ifdOffset,
							   int64 offsetDelta,
							   uint32 parentCode);

		virtual bool ParseMakerNoteIFD (dng_host &host,
										dng_stream &stream,
										uint64 ifdSize,
										uint64 ifdOffset,
										int64 offsetDelta,
										uint64 minOffset,
										uint64 maxOffset,
										uint32 parentCode);

		virtual void ParseMakerNote (dng_host &host,
									 dng_stream &stream,
									 uint32 makerNoteCount,
									 uint64 makerNoteOffset,
									 int64 offsetDelta,
									 uint64 minOffset,
									 uint64 maxOffset);
									 
		virtual void ParseSonyPrivateData (dng_host &host,
										   dng_stream &stream,
										   uint64 count,
										   uint64 oldOffset,
										   uint64 newOffset);
									 
		virtual void ParseDNGPrivateData (dng_host &host,
										  dng_stream &stream);

	protected:

		class RecursionProtector
			{
				
			private:

				uint32 &fDepth;

			public:

				RecursionProtector (uint32 &depth)
					:	fDepth (depth)
					{
					fDepth++;
					}

				~RecursionProtector ()
					{
					fDepth--;
					}
				
			};
		
	};
	
/*****************************************************************************/

#endif
	
/*****************************************************************************/
