/*******************************************************************************
 *  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.baselibs;

import cdac.medinfo.sdk.dcm30_04.commoninterface.IDataElement;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDataSet;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDicomValue;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDictionaryReader;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IItem;
import cdac.medinfo.sdk.dcm30_04.enums.EnumSetupDeviceType;
import cdac.medinfo.sdk.dcm30_04.enums.EnumWhitePointFlag;
import cdac.medinfo.sdk.dcm30_04.exceptions.ConditionFailedException;
import cdac.medinfo.sdk.dcm30_04.exceptions.InvalidMacroException;
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;

/**
 * This macro records the result of a Luminance Uniformity QA task for a Display Subsystem.
 * @author saloni
 *
 */
public class LuminanceUniformityResultMacro extends Macro
{
	

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;


	/**
	 * This constructor constructs a Macro with specified DataSet.
	 * @param objDataSet Collection of DataElements 
	 */
	public LuminanceUniformityResultMacro(IDataSet objDataSet)
	{
		super(objDataSet);
	}

	/**
	 * This constructor constructs a Macro with specified DataSet and DictionaryReader
	 * @param objDataSet specifies the DataSet
	 * @param objDictionaryReader specifies the DICOM Dictionary reader to be used 
	 */
	public LuminanceUniformityResultMacro(IDataSet objDataSet,IDictionaryReader objDictionaryReader)
	{
		super(objDataSet,objDictionaryReader);
	}

	/**
	 * This constructor constructs a Macro with the specified Item
	 * @param objItem specifies instance of Item class
	 */
	public LuminanceUniformityResultMacro(IItem objItem)
	{
		super(objItem);
	}

	/**
	 * This constructor constructs a Macro with the specified Item and DictionaryReader
	 * @param objItem specifies instance of Item class
	 * @param objDictionaryReader specifies the DICOM Dictionary reader to be used 
	 */
	public LuminanceUniformityResultMacro(IItem objItem,IDictionaryReader objDictionaryReader)
	{
		super(objItem, objDictionaryReader);
	}

	/**
	 * Validates all the attributes in LuminanceUniformityResultMacro
	 * @return boolean - Success -true, Failure -false.
	 * @throws InvalidMacroException throws InvalidMacroException If Mandatory or Conditional element fails.
	 */
	public boolean validate() throws InvalidMacroException
	{
		if(iMacroLevel == DicomConstants.DCM_MODULE_LEVEL_MACRO)
			return validate(objIDataSet);
		else if(iMacroLevel == DicomConstants.DCM_ITEM_LEVEL_MACRO)
			return validate(objIItem);
		return false;
	}

	/**
	 * Validates all the attributes in LuminanceUniformityResultMacro that are present in the DataSet
	 * @param objIDataSet collection of DataElements
	 * @return boolean - Success -true, Failure - false
	 * @throws InvalidMacroException throws InvalidMacroException If Mandatory or Conditional element fails.
	 */
	public static boolean validate(IDataSet objIDataSet) throws InvalidMacroException
	{
		try
		{ 

			//validate condition here
		}
		catch( ConditionFailedException ce)
		{
			if(DicomConfig.createInstance().isLoggingOn())
			{
				DicomLogger.getLogger().log(ce.getMessage());
			}
			throw new InvalidMacroException( LensometryMeasurementsMacro.class.getSimpleName() ,ce); 
		}
		catch( MandatoryMissingException me)
		{
			if(DicomConfig.createInstance().isLoggingOn())
			{
				DicomLogger.getLogger().log(me.getMessage());
			}
			throw new InvalidMacroException(LensometryMeasurementsMacro.class.getSimpleName() ,me);
		}
		return true;
	}

	/**
	 * Validates all the attributes in LuminanceUniformityResultMacro that are present in the DataSet
	 * @param objIItem collection of DataElements in a sequence
	 * @return boolean - Success -true, Failure - false
	 * @throws InvalidMacroException throws InvalidMacroException If Mandatory or Conditional element fails.
	 */
	public static boolean validate(IItem objIItem) throws InvalidMacroException
	{
		try
		{  
			//validate condition here
		}
		catch( ConditionFailedException ce)
		{
			if(DicomConfig.createInstance().isLoggingOn())
			{
				DicomLogger.getLogger().log(ce.getMessage());
			}
			throw new InvalidMacroException(LensometryMeasurementsMacro.class.getSimpleName(),ce); 
		}
		catch( MandatoryMissingException me)
		{
			if(DicomConfig.createInstance().isLoggingOn())
			{
				DicomLogger.getLogger().log(me.getMessage());
			}
			throw new InvalidMacroException(LensometryMeasurementsMacro.class.getSimpleName(),me);
		}
		return true;
	}
	
	/**
	 * Sets number of luminance measurements recorded.
	 * @param shNumberOfLuminancePoints short value of number of luminance measurements recorded.
	 */
	public void setNumberOfLuminancePoints(short shNumberOfLuminancePoints)
	{
		/* Accept the NumberOfLuminancePoints of type US.
		 * 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
		 */
		IDataElement objIDataElement = null;
		if(objITransferSyntax.getVRTransferSyntax() == DicomConstants.DCM_VR_IMPLICIT)	
			objIDataElement = new ImplicitDE(0x0028,0x701B,shNumberOfLuminancePoints,objIDictionaryReader);
		else
			objIDataElement = new ExplicitDE(0x0028,0x701B,DicomConstants.DCM_DT_US, shNumberOfLuminancePoints);

		addDataElement(objIDataElement);
	}

	/**
	 * Retrieves number of luminance measurements recorded.
	 * @return short - short value of number of luminance measurements recorded.
	 */
	public short getNumberOfLuminancePoints()
	{
		Object objValue = getValue(0x0028,0x701B);
		if(objValue != null)
			return Short.parseShort(objValue.toString());

		return DicomConstants.DCM_NO_VALUE;
	}
	/**
	 * Retrieves pre-initialized object of Measurement Pattern Code Sequence.If the module contains the sequence object it returns the same otherwise it creates the sequence adds to the module with proper initialization and then returns 	the object of sequence.
	 * @return LuminanceResponseSequence - instance of MeasurementPatternCodeSequence. 
	 */
	public MeasurementPatternCodeSequence getMeasurementPatternCodeSequence()
	{
		MeasurementPatternCodeSequence objMeasurementPatternCodeSequence = null;
		IDataElement objIDataElement =  getDataElement(0x0028, 0x702D); //getDataElement
		if(objIDataElement != null)
		{
			IDicomValue objIDicomValue = objIDataElement.getDicomValue();
			if(objIDicomValue != null)
				objMeasurementPatternCodeSequence = (MeasurementPatternCodeSequence)objIDicomValue;
		}
		else
		{
			DicomV3Factory objDicomV3Factory = DicomV3Factory.createInstance();
			int iVRTransferSyntax = objITransferSyntax.getVRTransferSyntax();
			objIDataElement = null;
			objMeasurementPatternCodeSequence = (MeasurementPatternCodeSequence)objDicomV3Factory.createSequence(0x0028, 0x702D, objITransferSyntax, objIDictionaryReader);

			if(iVRTransferSyntax == DicomConstants.DCM_VR_IMPLICIT)
				objIDataElement = new ImplicitDE(0x0028, 0x702D, objMeasurementPatternCodeSequence.getValue(), objIDictionaryReader);
			else
				objIDataElement = new ExplicitDE(0x0028, 0x702D, DicomConstants.DCM_DT_SQ, objMeasurementPatternCodeSequence.getValue());
			objIDataElement.setTransferSyntax(objITransferSyntax);
			if(objIDataElement != null)
				addDataElement(objIDataElement);
		}
		return objMeasurementPatternCodeSequence;
	}
	/**
	 * Sets the integer Digital Driving Level (DDL) at which the luminance values were measured.
	 * @param shDDLValue short value of the integer Digital Driving Level (DDL) at which the luminance values weremeasured.
	 */
	public void setDDLValue(short shDDLValue)
	{
		/* Accept the DDLValue of type US.
		 * 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
		 */
		IDataElement objIDataElement = null;
		if(objITransferSyntax.getVRTransferSyntax() == DicomConstants.DCM_VR_IMPLICIT)	
			objIDataElement = new ImplicitDE(0x0028,0x7017,shDDLValue,objIDictionaryReader);
		else
			objIDataElement = new ExplicitDE(0x0028,0x7017,DicomConstants.DCM_DT_US, shDDLValue);

		addDataElement(objIDataElement);
	}

	/**
	 * Retrieves the integer Digital Driving Level (DDL) at which the luminance values weremeasured.
	 * @return short - short value of the integer Digital Driving Level (DDL) at which the luminance values weremeasured.
	 */
	public short getDDLValue()
	{
		Object objValue = getValue(0x0028,0x7017);
		if(objValue != null)
			return Short.parseShort(objValue.toString());

		return DicomConstants.DCM_NO_VALUE;
	}
	/**
	 * Sets whether white point values were also recorded at each location.
	 *Enumerated Values:
	 *YES
	 *NO
	 * @param enumWhitePointFlag enum value of White Point Flag.
	 */
	public void setWhitePointFlag(EnumWhitePointFlag enumWhitePointFlag)
	{
		/* Accept the White Point Flag in String format of type CS.
		 * 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
		 */
		IDataElement objIDataElement = null;
		if(objITransferSyntax.getVRTransferSyntax() == DicomConstants.DCM_VR_IMPLICIT)
			objIDataElement = new ImplicitDE(0x0028,0x7021, enumWhitePointFlag.getValue(),objIDictionaryReader);
		else
			objIDataElement = new ExplicitDE(0x0028,0x7021,DicomConstants.DCM_DT_CS, enumWhitePointFlag.getValue());

		addDataElement(objIDataElement);
	}
	/**
	 * Return White Point Flag. 
	 * @return String - value of WhitePointFlag.
	 */
	public String getWhitePointFlag()
	{
		Object objValue = getValue(0x0028,0x7021);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	/**
	 * Retrieves pre-initialized object of Luminance Response Sequence.If the module contains the sequence object it returns the same otherwise it creates the sequence adds to the module with proper initialization and then returns 	the object of sequence.
	 * @return LuminanceResponseSequence - instance of LuminanceResponseSequence. 
	 */
	public LuminanceResponseSequence getLuminanceResponseSequence()
	{
		LuminanceResponseSequence objLuminanceResponseSequence = null;
		IDataElement objIDataElement =  getDataElement(0x0028, 0x701C); //getDataElement
		if(objIDataElement != null)
		{
			IDicomValue objIDicomValue = objIDataElement.getDicomValue();
			if(objIDicomValue != null)
				objLuminanceResponseSequence = (LuminanceResponseSequence)objIDicomValue;
		}
		else
		{
			DicomV3Factory objDicomV3Factory = DicomV3Factory.createInstance();
			int iVRTransferSyntax = objITransferSyntax.getVRTransferSyntax();
			objIDataElement = null;
			objLuminanceResponseSequence = (LuminanceResponseSequence)objDicomV3Factory.createSequence(0x0028, 0x701C, objITransferSyntax, objIDictionaryReader);

			if(iVRTransferSyntax == DicomConstants.DCM_VR_IMPLICIT)
				objIDataElement = new ImplicitDE(0x0028, 0x701C, objLuminanceResponseSequence.getValue(), objIDictionaryReader);
			else
				objIDataElement = new ExplicitDE(0x0028, 0x701C, DicomConstants.DCM_DT_SQ, objLuminanceResponseSequence.getValue());
			objIDataElement.setTransferSyntax(objITransferSyntax);
			if(objIDataElement != null)
				addDataElement(objIDataElement);
		}
		return objLuminanceResponseSequence;
	}
	/**
	 * Sets Reflected ambient light in candelas per square meter (cd/m2) when themeasurements were taken.
	 * @param shReflectedAmbientLight short value of Reflected ambient light in candelas per square meter (cd/m2) when themeasurements were taken.
	 */
	public void setReflectedAmbientLight(short shReflectedAmbientLight)
	{
		/* Accept the ReflectedAmbientLight of type US.
		 * 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
		 */
		IDataElement objIDataElement = null;
		if(objITransferSyntax.getVRTransferSyntax() == DicomConstants.DCM_VR_IMPLICIT)	
			objIDataElement = new ImplicitDE(0x2010,0x0160,shReflectedAmbientLight,objIDictionaryReader);
		else
			objIDataElement = new ExplicitDE(0x2010,0x0160,DicomConstants.DCM_DT_US, shReflectedAmbientLight);

		addDataElement(objIDataElement);
	}

	/**
	 * Retrieves Reflected ambient light in candelas per square meter (cd/m2) when themeasurements were taken.
	 * @return short - short value ofReflected ambient light in candelas per square meter (cd/m2) when themeasurements were taken.
	 */
	public short getReflectedAmbientLight()
	{
		Object objValue = getValue(0x2010,0x0160);
		if(objValue != null)
			return Short.parseShort(objValue.toString());
		return DicomConstants.DCM_NO_VALUE;
	}

	/**
	 * Sets the source of the ambient light value.
	 *Enumerated Values:
	 *DEFAULT :a configured default value was used.
	 *MEASURED:the value was measured at the time of the other measurements.
	 *PROVIDED:the value was provided by an external source.
	 * @param enumAmbientLightValueSource enum value of Ambient Light Value Source
	 */
	public void setAmbientLightValueSource(EnumSetupDeviceType enumAmbientLightValueSource)
	{
		/* Accept the AmbientLightValueSource in String format of type CS.
		 * 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
		 */
		IDataElement objIDataElement = null;
		if(objITransferSyntax.getVRTransferSyntax() == DicomConstants.DCM_VR_IMPLICIT)
			objIDataElement = new ImplicitDE(0x0028,0x7025, enumAmbientLightValueSource.getValue(),objIDictionaryReader);
		else
			objIDataElement = new ExplicitDE(0x0028,0x7025,DicomConstants.DCM_DT_CS, enumAmbientLightValueSource.getValue());

		addDataElement(objIDataElement);
	}
	/**
	 * Return Ambient Light Value Source
	 * @return String - value of AmbientLightValueSource
	 */
	public String getAmbientLightValueSource()
	{
		Object objValue = getValue(0x0028,0x7025);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
}
