/*******************************************************************************
 *  Copyright 2017-2018 Centre for Development of Advanced Computing(C-DAC), Pune
 *  
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *   http://www.apache.org/licenses/LICENSE-2.0
 *  
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *******************************************************************************/
package cdac.medinfo.sdk.dcm30_04.dicommodel.modules;

import cdac.medinfo.sdk.dcm30_04.baselibs.ContentIdentificationMacro;
import cdac.medinfo.sdk.dcm30_04.baselibs.DicomV3Factory;
import cdac.medinfo.sdk.dcm30_04.baselibs.ReferencedImageRealWorldValueMappingSequence;
import cdac.medinfo.sdk.dcm30_04.baselibs.Tag;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDataSet;
import cdac.medinfo.sdk.dcm30_04.commoninterface.ITag;

import cdac.medinfo.sdk.dcm30_04.exceptions.InvalidModuleException;
import cdac.medinfo.sdk.dcm30_04.exceptions.MandatoryMissingException;
import cdac.medinfo.sdk.dcm30_04.utils.DicomConfig;
import cdac.medinfo.sdk.dcm30_04.utils.DicomConstants;
import cdac.medinfo.sdk.dcm30_04.utils.DicomLogger;
import cdac.medinfo.sdk.dcm30_04.utils.ISingleCollection;
import cdac.medinfo.sdk.dcm30_04.utils.SingleCollection;
/**
 \* This module specifies the attributes of Real World Value Mapping Module.
 */
public class RealWorldValueMappingModule extends Module
{
	/**
	  * The obj single collection.
	  */
	 public static ISingleCollection<ITag> objSingleCollection = null;
		 

		/**
		 * Instantiates a new RealWorldValueMappingModule
		 * 
		 * @param objIDataSet the obj i data set
		 */
	 ContentIdentificationMacro objContentIdentificationMacro=null;
		public RealWorldValueMappingModule(IDataSet objIDataSet)
		{
			super(objIDataSet);
		}

		static
		{
			objSingleCollection = new SingleCollection<ITag>();
			objSingleCollection.add(new Tag(0x0008, 0x0023));
			objSingleCollection.add(new Tag(0x0008, 0x0033));
			objSingleCollection.add(new Tag(0x0040,0x9094));

		}

		/**
		 * This method validates each Attribute in the Module according to the Type
		 * of the Attribute.Attributes are of 5 types.
		 * Type 1,Type 2 are Mandatory:
		 * Mandatory Attributes have to present in the Module.
		 * Type 1C,2C are Conditional:
		 * Conditional Attributes' presence depend on a condition.
		 * If the condition is satisfied the Attribute has to be present.
		 * Type 3 are Optional
		 * Optional Attributes can be added as and when required.
		 * 
		 * @return boolean - returns validation status as success or failure
		 * 
		 * @throws InvalidModuleException - If validation of Module fails
		 */	
		public  boolean validateModule() throws InvalidModuleException
		{
			
				try
				{		
					if(!isPresent(0x0008, 0x0023))
					{
						throw new MandatoryMissingException("Missing Mandatory DataElement 0008,0023");
					}
					if(!isPresent(0x0008, 0x0033))
					{
						throw new MandatoryMissingException("Missing Mandatory DataElement 0008,0033");
					}
					if(!isPresent(0x0040,0x9094))
					{
						throw new MandatoryMissingException("Missing Mandatory DataElement 0040.9094");
					}
				
				}
				catch(MandatoryMissingException mme)
				{
					if(DicomConfig.createInstance().isLoggingOn())
						DicomLogger.getLogger().log(mme.getMessage());

					
						throw new InvalidModuleException(this.getClass().getSimpleName(),mme);

				}
			return true;
		}
		/**
		 * Sets date the content creation started.
		 * @param strContentDate String value of date the content creation started.
		 */
		public void setContentDate(String strContentDate)
		{
			/* Accept the date the content creation started. of type DA.
			 * Read the Transfer Syntax and check if ImplicitDE or ExplicitDE to create
			 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
			 * Set the iVRType
			 * Set length from the element
			 * Add this element to the Data Set
			 */
			addDataElement(0x0008, 0x0023, DicomConstants.DCM_DT_DA,strContentDate);
		}

		/**
		 * Retrieves date the content creation started.
		 * @return String - value of date the content creation started.
		 */
		public String getContentDate()
		{
			Object objValue = getValue(0x0008, 0x0023);
			if(objValue != null)
				return objValue.toString();
			return null;
		}

		/**
		 * Sets time the content creation started
		 * @param strContentTime String value of time the content creation started
		 */
		public void setContentTime(String strContentTime)
		{
			/* Accept time the content creation started of type TM.
			 * Read the Transfer Syntax and check if ImplicitDE or ExplicitDE to create
			 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
			 * Set the iVRType
			 * Set length from the element
			 * Add this element to the Data Set
			 */
			addDataElement(0x0008,0x0033, DicomConstants.DCM_DT_TM,strContentTime);
		}

		/**
		 * Retrieves time the content creation started
		 * @return String - value of time the content creation started
		 */
		public String getContentTime()
		{
			Object objValue = getValue(0x0008, 0x0033);
			if(objValue != null)
				return objValue.toString();
			return null;
		}
		/**
		 * Get the Instance of Content Identification Macro Attributes.Calling this method multiple times will return the same Marco instance that was created at first. Hence, any attributes in this Macro,if set multiple times will contain the value that was set in the last call to its setter method.
		 * 
		 * @return - object of Content Identification Macro Attributes which the user programmer can populate
		 */
		public ContentIdentificationMacro getContentIdentificationMacro()
		{
			if(objContentIdentificationMacro == null)
				objContentIdentificationMacro = new ContentIdentificationMacro(objIDataSet);
			return objContentIdentificationMacro; 
		}
		/**
		 * Retrieves Referenced Image Real WorldValue Mapping Sequence  
		 * @return - instance of Referenced Image Real WorldValue Mapping Sequence.
		 */
		public ReferencedImageRealWorldValueMappingSequence getReferencedImageRealWorldValueMappingSequence()
		{
			ReferencedImageRealWorldValueMappingSequence objReferencedImageRealWorldValueMappingSequence = (ReferencedImageRealWorldValueMappingSequence)getDicomValue(0x0040,0x9094);
			if(objReferencedImageRealWorldValueMappingSequence == null)
			{
				/*
				 * If the sequence object is not present in the DataSet, a new sequence object is created and
				 * the TransferSyntax and DictionaryReader is set into it as it is set in the Module. This ensures that 
				 * the DataElements getting added in the DataSet follow the same TransferSyntax and use the same
				 * DictionaryReader object as that of the module.
				 */
				DicomV3Factory objDicomV3Factory = DicomV3Factory.createInstance();
				objReferencedImageRealWorldValueMappingSequence = (ReferencedImageRealWorldValueMappingSequence)objDicomV3Factory.createSequence(0x0040,0x9094, objITransferSyntax, objIDictionaryReader);
				
				// This will add Data Element of SQ to the DataSet.
				addDataElement(0x0040,0x9094, DicomConstants.DCM_DT_SQ, objReferencedImageRealWorldValueMappingSequence.getValue());
			}
			return objReferencedImageRealWorldValueMappingSequence;
		}
		
		/**
		 * This method returns the vector of keys representing the DataElements
		 * that belong to this module.
		 * 
		 * @return vector of Tags - returns the vector containing the collection of tags
		 */
		public ISingleCollection<ITag> getVectorOfKeys()
		{
			return objSingleCollection;
		}
}
