/*******************************************************************************
 *  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.EnumAlphaLUTTransferFunction;
import cdac.medinfo.sdk.dcm30_04.enums.EnumDataPathID;
import cdac.medinfo.sdk.dcm30_04.enums.EnumRGBLUTTransferFunction;
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.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 Enhanced Palette Color Lookup Table Sequence .
 */

public class EnhancedPaletteColorLookupTableSequenceItem extends Item
{

		private static final long serialVersionUID = 1L;

		/**
		 * This constructor creates the item and internal code sequence macro with default TransferSyntax 
		 */
		EnhancedPaletteColorLookupTableSequenceItem()
		{
			super();
		}

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

		/**
		 * This constructor creates Enhanced Palette Color Lookup Table Sequence Item with specified TransferSyntax and specified DictionaryReader
		 * @param objTransferSyntax specifies the DICOM Standard defined TransfeSyntax
		 * @param objDictionaryReader specifies the DICOM Dictionary reader to be used 
		 */
		EnhancedPaletteColorLookupTableSequenceItem(ITransferSyntax objTransferSyntax, IDictionaryReader objDictionaryReader)
		{
			super(objTransferSyntax,objDictionaryReader);
		}
		/**
		 * Identifier of the data path in which this Palette Color Lookup Table isused.
		 *Enumerated Values:
		 *PRIMARY
		 *SECONDARY
		 *Each item shall have a distinct value of Data Path ID.
		 * @param enumDataPathID enum value of Setup Device Type.
		 */
		public void setDataPathID(EnumDataPathID enumDataPathID)
		{
			/* Accept the Data PathID 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,0x140E, enumDataPathID.getValue(),getDictionaryReader());
			else
				objIDataElement = new ExplicitDE(0x0028,0x140E,DicomConstants.DCM_DT_CS, enumDataPathID.getValue());

			addDataElement(objIDataElement);
		}
		/**
		 * Return DataPathID. 
		 * @return String - value of Data PathID.
		 */
		public String getDataPathID()
		{
			Object objValue = getValue(0x0028,0x140E);
			if(objValue != null)
				return objValue.toString();
			return null;
		}
		
		/**
		 * Specifies the mapping that takes place between the input value and RGBinput to the Blending Operation.
		 *Enumerated Values:
		 *EQUAL_RGB  Output is R=G=B=input value
		 *TABLE Output is RGB LUT values
		 * @param enumSetupDeviceType enum value of RGBLUTTransferFunction .
		 */
		public void setRGBLUTTransferFunction (EnumRGBLUTTransferFunction enumRGBLUTTransferFunction )
		{
			/* Accept the RGBLUTTransferFunction 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,0x140F, enumRGBLUTTransferFunction.getValue(),getDictionaryReader());
			else
				objIDataElement = new ExplicitDE(0x0028,0x140F,DicomConstants.DCM_DT_CS, enumRGBLUTTransferFunction.getValue());

			addDataElement(objIDataElement);
		}
		/**
		 * Return RGBLUTTransferFunction . 
		 * @return String - value of RGBLUTTransferFunction .
		 */
		public String getRGBLUTTransferFunction ()
		{
			Object objValue = getValue(0x0028,0x140F);
			if(objValue != null)
				return objValue.toString();
			return null;
		}
		
		/**
		 * Specifies the transformation that is used to create the Alpha input to theBlending LUTs.
		 *Note :Depending on the values of Blending LUT 1 Transfer Function(0028,1405) and Blending LUT 2 Transfer Function (0028,140D)the Alpha LUT value may be ignored. It is recommended thatIDENTITY be used if this is the case.
		 *Enumerated Values:
		 *NONE
		 *IDENTITY
		 *TABLE
		 * @param enumAlphaLUTTransferFunction enum value of AlphaLUTTransferFunction.
		 */
		public void setAlphaLUTTransferFunction(EnumAlphaLUTTransferFunction enumAlphaLUTTransferFunction)
		{
			/* Accept the Setup Device Type 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,0x1410, enumAlphaLUTTransferFunction.getValue(),getDictionaryReader());
			else
				objIDataElement = new ExplicitDE(0x0028,0x1410,DicomConstants.DCM_DT_CS, enumAlphaLUTTransferFunction.getValue());

			addDataElement(objIDataElement);
		}
		/**
		 * Return AlphaLUTTransferFunction. 
		 * @return String - value of AlphaLUTTransferFunction.
		 */
		public String getAlphaLUTTransferFunction()
		{
			Object objValue = getValue(0x0028,0x1410);
			if(objValue != null)
				return objValue.toString();
			return null;
		}
		/**
		 * Sets the value that specifies the format of the Red Palette Color Lookup Table Data(0028,1201).The second value (first stored pixel value mapped) shall be zero.
		 * @param sRedPaletteColorLookupTableDescriptor short array of RedPaletteColorLookupTableDescriptor values. 
		 */
		public void setRedPaletteColorLookupTableDescriptor(short[] sRedPaletteColorLookupTableDescriptor)
		{
			/* Accept the RedPaletteColorLookupTableDescriptor in short Array format of type US or SS.
			 * 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, 0x1101, sRedPaletteColorLookupTableDescriptor,objIDictionaryReader);
			else
				objIDataElement = new ExplicitDE(0x0028, 0x1101,DicomConstants.DCM_DT_US, sRedPaletteColorLookupTableDescriptor);
			addDataElement(objIDataElement);
		}
		/**
		 * Returns the format of the RedPaletteColorLookupTableDescriptor.
		 * @return short[] - short array of RedPaletteColorLookupTableDescriptor.
		 */
		public short[] getRedPaletteColorLookupTableDescriptor()
		{
			Object objValue = getValue(0x0028, 0x1101);
			if(objValue != null)
				return (short[])objValue;
			return null;
		}
		
		/**
		 * Sets the value that specifies the format of the Green Palette Color Lookup Table Data(0028,1202).The second value (first stored pixel value mapped) shall be zero.
		 * @param sGreenPaletteColorLookupTableDescriptor short array of LUT Descriptor values. 
		 */
		public void setGreenPaletteColorLookupTableDescriptor(short[] sGreenPaletteColorLookupTableDescriptor)
		{
			/* Accept the GreenPaletteColorLookupTableDescriptor in short Array format of type US or SS.
			 * 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, 0x1102, sGreenPaletteColorLookupTableDescriptor,objIDictionaryReader);
			else
				objIDataElement = new ExplicitDE(0x0028, 0x1102,DicomConstants.DCM_DT_US, sGreenPaletteColorLookupTableDescriptor);
			addDataElement(objIDataElement);
		}
		/**
		 * Returns the format of the GreenPaletteColorLookupTableDescriptor.
		 * @return short[] - short array of GreenPaletteColorLookupTableDescriptor.
		 */
		public short[] getGreenPaletteColorLookupTableDescriptor()
		{
			Object objValue = getValue(0x0028, 0x1102);
			if(objValue != null)
				return (short[])objValue;
			return null;
		}
		
		/**
		 * Sets the value that specifies the format of the Blue Palette Color Lookup Table Data(0028,1203).The second value (first stored pixel value mapped) shall be zero.
		 * @param sBluePaletteColorLookupTableDescriptor short array of LUT Descriptor values. 
		 */
		public void setBluePaletteColorLookupTableDescriptor(short[] sBluePaletteColorLookupTableDescriptor)
		{
			/* Accept the BluePaletteColorLookupTableDescriptor in short Array format of type US or SS.
			 * 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, 0x1103, sBluePaletteColorLookupTableDescriptor,objIDictionaryReader);
			else
				objIDataElement = new ExplicitDE(0x0028, 0x1103,DicomConstants.DCM_DT_US, sBluePaletteColorLookupTableDescriptor);
			addDataElement(objIDataElement);
		}
		/**
		 * Returns the format of the BluePaletteColorLookupTableDescriptor.
		 * @return short[] - short array of BluePaletteColorLookupTableDescriptor.
		 */
		public short[] getBluePaletteColorLookupTableDescriptor()
		{
			Object objValue = getValue(0x0028, 0x1103);
			if(objValue != null)
				return (short[])objValue;
			return null;
		}
		
		/**
		 * Sets the value that specifies the format of the Alpha Palette Color Lookup Table Data.The second value (first stored pixel value mapped) shall be zero.
		 * @param sAlphaPaletteColorLookupTableDescriptor short array of LUT Descriptor values. 
		 */
		public void setAlphaPaletteColorLookupTableDescriptor(short[] sAlphaPaletteColorLookupTableDescriptor)
		{
			/* Accept the AlphaPaletteColorLookupTableDescriptor in short Array format of type US or SS.
			 * 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, 0x1104, sAlphaPaletteColorLookupTableDescriptor,objIDictionaryReader);
			else
				objIDataElement = new ExplicitDE(0x0028, 0x1104,DicomConstants.DCM_DT_US, sAlphaPaletteColorLookupTableDescriptor);
			addDataElement(objIDataElement);
		}
		/**
		 * Returns the format of the AlphaPaletteColorLookupTableDescriptor.
		 * @return short[] - short array of AlphaPaletteColorLookupTableDescriptor.
		 */
		public short[] getAlphaPaletteColorLookupTableDescriptor()
		{
			Object objValue = getValue(0x0028, 0x1104);
			if(objValue != null)
				return (short[])objValue;
			return null;
		}
		/**
		 * Sets Red Palette Color Lookup Table Data.
		 * @param shRedPaletteColorLookupTableData short value of Red Palette Color Lookup Table Data
		 */
		public void setRedPaletteColorLookupTableData(short shRedPaletteColorLookupTableData)
		{
			/* Accept the RedPaletteColorLookupTableData 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,0x1201,shRedPaletteColorLookupTableData,getDictionaryReader());
			else
				objIDataElement = new ExplicitDE(0x0028,0x1201,DicomConstants.DCM_DT_US, shRedPaletteColorLookupTableData);

			addDataElement(objIDataElement);
		}

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

		
		/**
		 * Sets Green Palette Color Lookup Table Data.
		 * @param shGreenPaletteColorLookupTableData short value of Green Palette Color Lookup Table Data.
		 */
		public void setGreenPaletteColorLookupTableData(short shGreenPaletteColorLookupTableData)
		{
			/* Accept the GreenPaletteColorLookupTableData 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,0x1202,shGreenPaletteColorLookupTableData,getDictionaryReader());
			else
				objIDataElement = new ExplicitDE(0x0028,0x1202,DicomConstants.DCM_DT_US, shGreenPaletteColorLookupTableData);

			addDataElement(objIDataElement);
		}

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

		
		/**
		 * Sets Blue Palette Color Lookup Table Data.
		 * @param shBluePaletteColorLookupTableData short value of Blue Palette Color Lookup Table Data.
		 */
		public void setBluePaletteColorLookupTableData(short shBluePaletteColorLookupTableData)
		{
			/* Accept the BluePaletteColorLookupTableData 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,0x1203,shBluePaletteColorLookupTableData,getDictionaryReader());
			else
				objIDataElement = new ExplicitDE(0x0028,0x1203,DicomConstants.DCM_DT_US, shBluePaletteColorLookupTableData);

			addDataElement(objIDataElement);
		}

		/**
		 * Retrieves Blue Palette Color Lookup Table Data.
		 * @return short - short value of Blue Palette Color Lookup Table Data.
		 */
		public short getBluePaletteColorLookupTableData()
		{
			Object objValue = getValue(0x0028,0x1203);
			if(objValue != null)
				return Short.parseShort(objValue.toString());
			return DicomConstants.DCM_NO_VALUE;
		}

		
		/**
		 * Sets Alpha LUT contains the blending values for the data frames.
		 * @param shAlphaPaletteColorLookupTableData short value of Alpha Palette Color LookupTable Data
		 */
		public void setAlphaPaletteColorLookupTableData(short shAlphaPaletteColorLookupTableData)
		{
			/* Accept the AlphaPaletteColorLookupTableData 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,0x1204,shAlphaPaletteColorLookupTableData,getDictionaryReader());
			else
				objIDataElement = new ExplicitDE(0x0028,0x1204,DicomConstants.DCM_DT_US, shAlphaPaletteColorLookupTableData);

			addDataElement(objIDataElement);
		}

		/**
		 * Retrieves Alpha Palette Color LookupTable Data
		 * @return short - short value of Alpha Palette Color LookupTable Data
		 */
		public short getAlphaPaletteColorLookupTableData()
		{
			Object objValue = getValue(0x0028,0x1204);
			if(objValue != null)
				return Short.parseShort(objValue.toString());
			return DicomConstants.DCM_NO_VALUE;
		}

		/**
		 * Validates all the attributes in Enhanced Palette Color Lookup Table Sequence Item  that are present in the DataSet
		 * @return boolean - Success -true, Failure - false
		 * @throws InvalidItemException If Mandatory or Conditional element fails.
		 */
		public boolean validateForModule()  throws InvalidItemException
		{
			try
			{
				//validation of mandatory elements
				if(!contains(0x0028,0x140E))
					throw new MandatoryMissingException("0028,140E");
				if(!contains(0x0028,0x140F))
					throw new MandatoryMissingException("0028,140F");
				if(!contains(0x0028,0x1410))
					throw new MandatoryMissingException("0028,1410");
				
				//validation of conditional elements
				if(getDataForTag(0x0028, 0x140F).getValue().toString().equals(EnumRGBLUTTransferFunction.TABLE))
					if(!contains(0x0028,0x1101))
						throw new ConditionFailedException("value for conditional Element 0028,1101 required if value of 0028,140F is TABLE.");
				if(getDataForTag(0x0028, 0x140F).getValue().toString().equals(EnumRGBLUTTransferFunction.TABLE))
					if(!contains(0x0028,0x1102))
						throw new ConditionFailedException("value for conditional Element 0028,1102 required if value of 0028,140F is TABLE.");
				if(getDataForTag(0x0028, 0x140F).getValue().toString().equals(EnumRGBLUTTransferFunction.TABLE))
					if(!contains(0x0028,0x1103))
						throw new ConditionFailedException("value for conditional Element 0028,1103 required if value of 0028,140F is TABLE.");
				if(getDataForTag(0x0028, 0x1410).getValue().toString().equals(EnumAlphaLUTTransferFunction.TABLE))
					if(!contains(0x0028,0x1104))
						throw new ConditionFailedException("value for conditional Element 0028,1104 required if value of 0028,1410 is TABLE.");
				
				
				if(getDataForTag(0x0028, 0x140F).getValue().toString().equals(EnumRGBLUTTransferFunction.TABLE))
					if(!contains(0x0028,0x1201))
						throw new ConditionFailedException("value for conditional Element 0028,1201 required if value of 0028,140F is TABLE.");
				if(getDataForTag(0x0028, 0x140F).getValue().toString().equals(EnumRGBLUTTransferFunction.TABLE))
					if(!contains(0x0028,0x1202))
						throw new ConditionFailedException("value for conditional Element 0028,1202 required if value of 0028,140F is TABLE.");
				if(getDataForTag(0x0028, 0x140F).getValue().toString().equals(EnumRGBLUTTransferFunction.TABLE))
					if(!contains(0x0028,0x1203))
						throw new ConditionFailedException("value for conditional Element 0028,1203 required if value of 0028,140F is TABLE.");
				if(getDataForTag(0x0028, 0x1410).getValue().toString().equals(EnumAlphaLUTTransferFunction.TABLE))
					if(!contains(0x0028,0x1204))
						throw new ConditionFailedException("value for conditional Element 0028,1204 required if value of 0028,1410 is TABLE.");
			}
			catch( MandatoryMissingException me)
			{
				if(DicomConfig.createInstance().isLoggingOn())
				{
					DicomLogger.getLogger().log(me.getMessage());
				}
				throw new InvalidItemException(this.getClass().getSimpleName(),me);
			}
			catch( ConditionFailedException ce)
			{
				if(DicomConfig.createInstance().isLoggingOn())
				{
					DicomLogger.getLogger().log(ce.getMessage());
				}
				throw new InvalidItemException(this.getClass().getSimpleName(),ce); 
			}
			return true;
		}
		
	}
