/*******************************************************************************
 *  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.IDictionaryReader;
import cdac.medinfo.sdk.dcm30_04.commoninterface.ITransferSyntax;
import cdac.medinfo.sdk.dcm30_04.enums.EnumBlendingLUT2TransferFunction;
import cdac.medinfo.sdk.dcm30_04.exceptions.ConditionFailedException;
import cdac.medinfo.sdk.dcm30_04.exceptions.InvalidItemException;
import cdac.medinfo.sdk.dcm30_04.exceptions.MandatoryMissingException;
import cdac.medinfo.sdk.dcm30_04.exceptions.ValidationException;
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 item class contains the methods to set, get and validate the attribute present in Blending LUT-2 Sequence .
 */
public class BlendingLUT2SequenceItem extends Item
{

	private static final long serialVersionUID = 1L;

	/**
	 * This constructor creates the item and with default TransferSyntax 
	 */
	BlendingLUT2SequenceItem()
	{
		super();
	}

	/**
	 * This constructor creates the item with default TransferSyntax.
	 * @param objITransferSyntax specifies the DICOM Standard defined TransfeSyntax 
	 */
	BlendingLUT2SequenceItem(ITransferSyntax objITransferSyntax)
	{
		super(objITransferSyntax);
	}

	/**
	 * This constructor creates BlendingLUT2SequenceItem with specified TransferSyntax and
	 * specified DictionaryReader
	 * @param objTransferSyntax specifies the DICOM Standard defined TransfeSyntax
	 * @param objDictionaryReader specifies the DICOM Dictionary reader to be used 
	 */
	BlendingLUT2SequenceItem(ITransferSyntax objTransferSyntax, IDictionaryReader objDictionaryReader)
	{
		super(objTransferSyntax,objDictionaryReader);
	}

	/**
	 * It Specifies the algorithm used to determine the output value of BlendingLUT 2.
     *Enumerated Values:
     *CONSTANT
     *ONE_MINUS
     *ALPHA_1
     *ALPHA_2
     *TABLE
	 * @param enumBlendingLUT2TransferFunction -enum value of BlendingLUT1TransferFunction.
	 */
	public void setBlendingLUT2TransferFunction(EnumBlendingLUT2TransferFunction enumBlendingLUT2TransferFunction)
	{
		/* Accept the BlendingLUT2TransferFunction 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,0x140D, enumBlendingLUT2TransferFunction.getValue(),getDictionaryReader());
		else
			objIDataElement = new ExplicitDE(0x0028,0x140D,DicomConstants.DCM_DT_CS, enumBlendingLUT2TransferFunction.getValue());

		addDataElement(objIDataElement);


	}
	/**
	 * Returns BlendingLUT2TransferFunction. 
	 * @return String - value of BlendingLUT2TransferFunction.
	 */
	public String getBlendingLUT2TransferFunction()
	{
		Object objValue = getValue(0x0028,0x140D);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	/**
	 * Sets the BlendingWeightConstant.
	 * @param dblBlendingWeightConstant Double value of Blending Weight Constant.
	 */
	public void setBlendingWeightConstant(double dblBlendingWeightConstant)
	{
		/*Accept the BlendingWeightConstant in double format of type FD.
		 * 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,0x1406, dblBlendingWeightConstant,getDictionaryReader());
		else
			objIDataElement = new ExplicitDE(0x0028,0x1406,DicomConstants.DCM_DT_FD, dblBlendingWeightConstant);

		addDataElement(objIDataElement);
	}
	/**
	 * Retrieves the BlendingWeightConstant.
	 * @return double - double value of BlendingWeightConstant
	 */
	public double getBlendingWeightConstant()
	{
		Object objValue = getValue(0x0028,0x1406);
		if(objValue != null)
			return Double.parseDouble(objValue.toString());
		return DicomConstants.DCM_NO_VALUE;
	}
	
	/**
	 * Sets the BlendingLookupTableDescriptor.
	 * @param arrShBlendingLookupTableDescriptor -Short value of Blending Lookup Table Descriptor.
	 */
	/*Accept the BlendingLookupTableDescriptor in Array of short format 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
	 */
	public void setBlendingLookupTableDescriptor(short[] arrShBlendingLookupTableDescriptor)
	{
		IDataElement objIDataElement = null;
		if(objITransferSyntax.getVRTransferSyntax() == DicomConstants.DCM_VR_IMPLICIT)	
			objIDataElement = new ImplicitDE(0x0028, 0x1407, arrShBlendingLookupTableDescriptor,getDictionaryReader());
		else
			objIDataElement = new ExplicitDE(0x0028, 0x1407,DicomConstants.DCM_DT_US, arrShBlendingLookupTableDescriptor);

		addDataElement(objIDataElement);
	}

	/**
	 * Retrieves BlendingLookupTableDescriptor.
	 * @return short Array - BlendingLookupTableDescriptor.
	 */
	public short[] getBlendingLookupTableDescriptor()
	{
		Object objValue = getValue(0x0028, 0x1407);
		if(objValue != null)
			return (short[])objValue;
		return null;
	}
	/**
	 * Contains the Blending Lookup Table values for this Weight input to theBlending Operation.
	 * @param shBlendingLookupTableData short value of Number of significant bits
	 */
	public void setBlendingLookupTableData(short shBlendingLookupTableData)
	{
		/* Accept the BlendingLookupTableData of type OW.
		 * 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,0x1408,shBlendingLookupTableData,getDictionaryReader());
		else
			objIDataElement = new ExplicitDE(0x0028,0x1408,DicomConstants.DCM_DT_US, shBlendingLookupTableData);

		addDataElement(objIDataElement);
	}

	/**
	 * Retrieves BlendingLookupTableData
	 * @return short - short value of BlendingLookupTableData
	 */
	public short getBlendingLookupTableData()
	{
		Object objValue = getValue(0x0028,0x1408);
		if(objValue != null)
			return Short.parseShort(objValue.toString());
		return DicomConstants.DCM_NO_VALUE;
	}

	/**
	 * Validates all the attributes in BlendingLUT1SequenceItem that are present in the DataSet
	 * @return boolean - Success -true, Failure - false
	 * @throws InvalidItemException throws InvalidItemException If Mandatory or Conditional element fails.
	 */
	public boolean validateForModule() throws InvalidItemException
	{
		try{
			if(!contains(0x0028,0x140D))
				throw new MandatoryMissingException("(0028,140D)");
			if(getDataForTag(0x0028, 0x140D).getValue().toString().equals(EnumBlendingLUT2TransferFunction.CONSTANT))
				if(!contains(0x0028,0x1406))
					throw new ConditionFailedException("value for conditional Element 0x0028,0x1406 required if value of (0028,140D) is CONSTANT");
			if(getDataForTag(0x0028, 0x140D).getValue().toString().equals(EnumBlendingLUT2TransferFunction.TABLE))
				if(!contains(0x0028,0x1407))
					throw new ConditionFailedException("value for conditional Element 0x0028,0x1407 required if value of (0028,140D) is TABLE");
			if(getDataForTag(0x0028, 0x140D).getValue().toString().equals(EnumBlendingLUT2TransferFunction.TABLE))
				if(!contains(0x0028,0x1408))
					throw new ConditionFailedException("value for conditional Element 0x0028,0x1408 required if value of (0028,140D) is TABLE");
			
		}
		catch(ConditionFailedException ce)
		{
			if(DicomConfig.createInstance().isLoggingOn())
			{
				DicomLogger.getLogger().log(ce.getMessage());
			}
			throw new ValidationException(this.getClass().getSimpleName(),ce); 
		}
		catch(MandatoryMissingException me)
		{
			if(DicomConfig.createInstance().isLoggingOn())
			{
				DicomLogger.getLogger().log(me.getMessage());
			}
			throw new InvalidItemException(this.getClass().getSimpleName(),me);
		}
		return true;
	}
}
