/*******************************************************************************
 *  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.services.print.printsinkimpl;

import cdac.medinfo.sdk.dcm30_04.baselibs.DicomV3Factory;
import cdac.medinfo.sdk.dcm30_04.baselibs.ReferencedFilmSessionSequence;
import cdac.medinfo.sdk.dcm30_04.baselibs.ReferencedPresentationLUTSequence;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDataSet;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDictionaryReader;
import cdac.medinfo.sdk.dcm30_04.commoninterface.ITransferSyntax;
import cdac.medinfo.sdk.dcm30_04.enums.EnumBorderDensity;
import cdac.medinfo.sdk.dcm30_04.enums.EnumEmptyImageDensity;
import cdac.medinfo.sdk.dcm30_04.enums.EnumFilmOrientation;
import cdac.medinfo.sdk.dcm30_04.enums.EnumFilmSizeID;
import cdac.medinfo.sdk.dcm30_04.enums.EnumImageDisplayFormat;
import cdac.medinfo.sdk.dcm30_04.enums.EnumMagnificationType;
import cdac.medinfo.sdk.dcm30_04.enums.EnumRequestedResolutionID;
import cdac.medinfo.sdk.dcm30_04.enums.EnumTrim;
import cdac.medinfo.sdk.dcm30_04.utils.DicomConstants;

/**
 *  This class contains the Attributes required for Query Model. Also contains methods to populate and fill dataset of Query Model.
 */
public class NCreateFilmBoxAttribute extends Attributes
{
	
	/**
	 * This is default Constructor for NCreateFilmBoxAttribute.
	 */
	public NCreateFilmBoxAttribute() {
		super();
	}

	/**
	 * Sets Type of image display format. Enumerated Values:
	 * STANDARD\C,R       : film contains equal size rectangular image boxes with R rows of image boxes and C columns
	 * of image boxes; C and R are integers.
	 * ROW\R1,R2,R3, etc. : film contains rows with equal size rectangular image boxes with R1 image boxes
	 * in the first row, R2 image boxes in second row, R3 image boxes in third row, etc.;
	 * R1, R2, R3, etc. are integers.
	 * COL\C1,C2,C3, etc. : film contains columns with equal size rectangular image boxes with C1 image
	 * boxes in the first column, C2 image boxes in second column, C3 image boxes in third
	 * column, etc.; C1,C2, C3, etc. are integers.
	 * SLIDE              : film contains 35mm slides; the number of slides for a particular film size is configuration
	 * dependent.
	 * SUPERSLIDE 		  :	film contains 40mm slides; the number of slides for a particular film size is
	 * configuration dependent.
	 * CUSTOM\i 		  : film contains a customized ordering of rectangular image boxes; i identifies the image
	 * display format; the definition of the image display formats is defined in the
	 * Conformance Statement; i is an integer.
	 * 
	 * @param enumImageDisplayFormat the enum image display format
	 */
	public void setImageDisplayFormat(EnumImageDisplayFormat  enumImageDisplayFormat)
	{
		/*Accept Image Display Format in String format of type ST.
		 * 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 Hash Map
		 */
		addDataElement(0x2010,0x0010, DicomConstants.DCM_DT_ST, enumImageDisplayFormat.getValue());
	}
	
	/**
	 * Return Type of image display format.
	 * 
	 * @return String - String value of Image Display Format.
	 */
	public String getImageDisplayFormat()
	{
		Object objValue = getValue(0x2010,0x0010);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	
	/**
	 * Retrieves a sequence which provides references to a Film Session SOP Class/Instance pairs.
	 * 
	 * @return - instance of {@link ReferencedFilmSessionSequence}
	 */
	public ReferencedFilmSessionSequence getReferencedFilmSessionSequence()
	{
		ReferencedFilmSessionSequence objReferencedFilmSessionSequence = (ReferencedFilmSessionSequence)getDicomValue(0x2010,0x0500);
		if(objReferencedFilmSessionSequence == 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.
			 */
			ITransferSyntax objITransferSyntax = getDataSet().getTransferSyntax();
			IDictionaryReader objIDictionaryReader = getDataSet().getDictionaryReader();
			
			DicomV3Factory objDicomV3Factory = DicomV3Factory.createInstance();
			objReferencedFilmSessionSequence = (ReferencedFilmSessionSequence)objDicomV3Factory.createSequence(0x2010,0x0500, objITransferSyntax, objIDictionaryReader);
			
			// This will add Data Element of SQ to the DataSet.
			addDataElement(0x2010,0x0500, DicomConstants.DCM_DT_SQ, objReferencedFilmSessionSequence.getValue());
		}
		return objReferencedFilmSessionSequence;
	}
	
	/**
	 * Sets Film orientation.
	 * Enumerated Values:
	 * PORTRAIT = vertical film position.
	 * LANDSCAPE = horizontal film position.
	 * 
	 * @param enumFilmOrientation  String value of Film Orientation.
	 */
	public void setFilmOrientation(EnumFilmOrientation enumFilmOrientation)
	{
		/* Accept Film Orientation 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 Hash Map
		 */
		addDataElement(0x2010,0x0040, DicomConstants.DCM_DT_CS, enumFilmOrientation.getValue());
	}

	/**
	 * Return Film orientation.
	 * 
	 * @return String - String value of Film orientation.
	 */
	public String getFilmOrientation()
	{
		Object objValue = getValue(0x2010,0x0040);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Sets Film size identification.
	 * Defined Terms: 8INX10IN,8_5INX11IN,10INX12IN,10INX14IN,11INX14IN,,11INX17IN,14INX14IN,
	 * 14INX17IN,24CMX24CM,24CMX30CM,A4,A3.
	 * 
	 * @param enumFilmSizeID  String value of Film Size ID.
	 */
	public void setFilmSizeID(EnumFilmSizeID enumFilmSizeID)
	{
		/* Accept Film Size ID 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 Hash Map
		 */
		addDataElement(0x2010,0x0050, DicomConstants.DCM_DT_CS, enumFilmSizeID.getValue());
	}

	/**
	 * Return Film size identification.
	 * 
	 * @return String - String value of Film size ID.
	 */
	public String getFilmSizeID()
	{
		Object objValue = getValue(0x2010,0x0050);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Sets interpolation type by which the printer magnifies or decimates the image in order to fit the image in the
	 * image box on film.
	 * Defined Terms: REPLICATE, BILINEAR,CUBIC,NONE.
	 * 
	 * @param enumMagnificationType String value of Magnification Type.
	 */
	public void setMagnificationType(EnumMagnificationType enumMagnificationType)
	{
		/* Accept Magnification 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 Hash Map
		 */
		addDataElement(0x2010,0x0060, DicomConstants.DCM_DT_CS, enumMagnificationType.getValue());
	}

	/**
	 * Return interpolation type by which the printer magnifies or decimates the image in order to fit the image in the
	 * image box on film.
	 * 
	 * @return String - String value of Magnification Type.
	 */
	public String getMagnificationType()
	{
		Object objValue = getValue(0x2010,0x0060);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	
	/**
	 * Sets maximum density of the images on the film, expressed in hundredths of OD. If Max Density is
	 * higher than maximum printer density than Max Density is set to maximum printer density.
	 * 
	 * @param shMaxDensity - short value of Max Density.
	 */
	public void setMaxDensity(short shMaxDensity)
	{
		/* Accept Max Density in String 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 Hash Map
		 */
		addDataElement(0x2010,0x0130, DicomConstants.DCM_DT_US, shMaxDensity);
	}

	/**
	 * Return maximum density of the images on the film, expressed in hundredths of OD.
	 * 
	 * @return short - short value of Max Density.
	 */
	public short getMaxDensity()
	{
		Object objValue = getValue(0x2010,0x0130);
		if(objValue != null)
			return Short.parseShort(objValue.toString());
		return DicomConstants.DCM_NO_VALUE;
	}
	
	/**
	 * Sets character string that contains either the ID of the printer configuration table that contains a set of
	 * values for implementation specific print parameters (e.g. perception LUT related parameters) or one or
	 * more configuration data values, encoded as characters.
	 * 
	 * @param strConfigurationInformation - String value of Configuration Information.
	 */
	public void setConfigurationInformation(String strConfigurationInformation)
	{
		/* Accept Configuration Information in String format of type ST.
		 * 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 Hash Map
		 */
		addDataElement(0x2010,0x0150, DicomConstants.DCM_DT_ST, strConfigurationInformation);
	}

	/**
	 * Return character string that contains either the ID of the printer configuration table that contains a set of
	 * values for implementation specific print parameters (e.g. perception LUT related parameters) or one or
	 * more configuration data values, encoded as characters.
	 * 
	 * @return String - String value of Configuration Information.
	 */
	public String getConfigurationInformation()
	{
		Object objValue = getValue(0x2010,0x0150);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	
	/**
	 * Retrieves a sequence which provides references to a Presentation LUT related SOP Class/Instance pairs.
	 * 
	 * @return - instance of {@link ReferencedPresentationLUTSequence}
	 */
	public ReferencedPresentationLUTSequence getReferencedPresentationLUTSequence()
	{
		ReferencedPresentationLUTSequence objReferencedPresentationLUTSequence = (ReferencedPresentationLUTSequence)getDicomValue(0x2050,0x0500);
		if(objReferencedPresentationLUTSequence == 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.
			 */
			ITransferSyntax objITransferSyntax = getDataSet().getTransferSyntax();
			IDictionaryReader objIDictionaryReader = getDataSet().getDictionaryReader();
			
			DicomV3Factory objDicomV3Factory = DicomV3Factory.createInstance();
			objReferencedPresentationLUTSequence = (ReferencedPresentationLUTSequence)objDicomV3Factory.createSequence(0x2050,0x0500, objITransferSyntax, objIDictionaryReader);
			
			// This will add Data Element of SQ to the DataSet.
			addDataElement(0x2050,0x0500, DicomConstants.DCM_DT_SQ, objReferencedPresentationLUTSequence.getValue());
		}
		return objReferencedPresentationLUTSequence;
	}
	
	/**
	 * Sets identification of annotation display format. The definition of the annotation display formats and the
	 * annotation box position sequence are defined in the Conformance Statement.
	 * 
	 * @param strAnnotationDisplayFormatID String value of Annotation Display Format ID.
	 */
	public void setAnnotationDisplayFormatID(String strAnnotationDisplayFormatID)
	{
		/* Accept Annotation Display Format ID 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 Hash Map
		 */
		addDataElement(0x2010,0x0030, DicomConstants.DCM_DT_CS, strAnnotationDisplayFormatID);
	}

	/**
	 * Return identification of annotation display format.
	 * 
	 * @return String - String value of Annotation Display Format ID.
	 */
	public String getAnnotationDisplayFormatID()
	{
		Object objValue = getValue(0x2010,0x0030);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	
	/**
	 * Sets value that specifies the type of the interpolation function. Values are defined in Conformance
	 * Statement. Only valid for Magnification Type (2010,0060) = CUBIC.
	 * 
	 * @param strSmoothingType String value of Smoothing Type.
	 */
	public void setSmoothingType(String strSmoothingType)
	{
		/* Accept Smoothing 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 Hash Map
		 */
		addDataElement(0x2010,0x0080, DicomConstants.DCM_DT_CS, strSmoothingType);
	}

	/**
	 * Return value that specifies the type of the interpolation function.
	 * 
	 * @return String - String value of Smoothing Type.
	 */
	public String getSmoothingType()
	{
		Object objValue = getValue(0x2010,0x0080);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Sets density of the film areas surrounding and between images on the film.
	 * Defined Terms:
	 * 1) BLACK
	 * 2) WHITE
	 * 3) i where i represents the desired density in hundreds of OD (e.g. 150 corresponds with 1.5 OD)
	 * 
	 * @param enumBorderDensity the enum border density
	 */
	public void setBorderDensity(EnumBorderDensity  enumBorderDensity)
	{
		/* Accept Border Density 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 Hash Map
		 */
		addDataElement(0x2010,0x0100, DicomConstants.DCM_DT_CS, enumBorderDensity.getValue());
	}

	/**
	 * Return density of the film areas surrounding and between images on the film.
	 * 
	 * @return String - String value of Border Density.
	 */
	public String getBorderDensity()
	{
		Object objValue = getValue(0x2010,0x0100);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Sets density of the image box area on the film that contains no image.
	 * Defined Terms:
	 * 1) BLACK
	 * 2) WHITE
	 * 3) i where i represents the desired density in hundreds of OD (e.g. 150 corresponds with 1.5 OD)
	 * 
	 * @param enumEmptyImageDensity the enum empty image density
	 */
	public void setEmptyImageDensity(EnumEmptyImageDensity enumEmptyImageDensity)
	{
		/* Accept Empty Image Density 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 Hash Map
		 */
		addDataElement(0x2010,0x0110, DicomConstants.DCM_DT_CS, enumEmptyImageDensity.getValue());
	}

	/**
	 * Return density of the image box area on the film that contains no image.
	 * 
	 * @return String - String value of Empty Image Density.
	 */
	public String getEmptyImageDensity()
	{
		Object objValue = getValue(0x2010,0x0110);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Sets minimum density of the images on the film, expressed in hundredths of OD. If Min Density is
	 * lower than minimum printer density than Min Density is set to minimum printer density.
	 * 
	 * @param shMinDensity - short value of Min Density.
	 */
	public void setMinDensity(short shMinDensity)
	{
		/* Accept Min Density in String 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 Hash Map
		 */
		addDataElement(0x2010,0x0120, DicomConstants.DCM_DT_US, shMinDensity);
	}

	/**
	 * Return minimum density of the images on the film, expressed in hundredths of OD.
	 * 
	 * @return short - short value of Min Density.
	 */
	public short getMinDensity()
	{
		Object objValue = getValue(0x2010,0x0120);
		if(objValue != null)
			return Short.parseShort(objValue.toString());
		return DicomConstants.DCM_NO_VALUE;
	}
	
	/**
	 * Sets whether a trim box shall be printed surrounding each image on the film.
	 * Enumerated Values:
	 * 1) YES
	 * 2) NO.
	 * 
	 * @param enumTrim the enum trim
	 */
	public void setTrim(EnumTrim  enumTrim)
	{
		/* Accept Trim 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 Hash Map
		 */
		addDataElement(0x2010,0x0140, DicomConstants.DCM_DT_CS, enumTrim.getValue());
	}

	/**
	 * Return whether a trim box shall be printed surrounding each image on the film.
	 * 
	 * @return String - String value of Trim.
	 */
	public String getTrim()
	{
		Object objValue = getValue(0x2010,0x0140);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	
	/**
	 * Sets luminance of lightbox illuminating a piece of transmissive film, or for the case of reflective media,
	 * luminance obtainable from diffuse reflection of the illumination present.
	 * 
	 * @param shIllumination - short value of Illumination.
	 */
	public void setIllumination(short shIllumination)
	{
		/* Accept Illumination in String 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 Hash Map
		 */
		addDataElement(0x2010,0x015E, DicomConstants.DCM_DT_US, shIllumination);
	}

	/**
	 * Return luminance of lightbox illuminating a piece of transmissive film, or for the case of reflective media,
	 * luminance obtainable from diffuse reflection of the illumination present.
	 * 
	 * @return short - short value of Illumination.
	 */
	public short getIllumination()
	{
		Object objValue = getValue(0x2010,0x015E);
		if(objValue != null)
			return Short.parseShort(objValue.toString());
		return DicomConstants.DCM_NO_VALUE;
	}

	/**
	 * Sets luminance contribution due to reflected ambient light.
	 * 
	 * @param shReflectedAmbientLight the sh reflected ambient light
	 */
	public void setReflectedAmbientLight(short shReflectedAmbientLight)
	{
		/* Accept Reflected Ambient Light in String 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 Hash Map
		 */
		addDataElement(0x2010,0x0160, DicomConstants.DCM_DT_US, shReflectedAmbientLight);
	}

	/**
	 * Return luminance contribution due to reflected ambient light.
	 * 
	 * @return short - short value of Reflected Ambient Light.
	 */
	public short getReflectedAmbientLight()
	{
		Object objValue = getValue(0x2010,0x0160);
		if(objValue != null)
			return Short.parseShort(objValue.toString());
		return DicomConstants.DCM_NO_VALUE;
	}

	/**
	 * Sets the resolution at which images in this Film Box are to be printed.
	 * Defined Terms:
	 * 1) STANDARD = approximately 4k x 5k printable pixels on a 14 x 17 inch film
	 * 2) HIGH = Approximately twice the resolution of STANDARD.
	 * 
	 * @param enumRequestedResolutionID the enum requested resolution id
	 */
	public void setRequestedResolutionID(EnumRequestedResolutionID enumRequestedResolutionID)
	{
		/* Accept Requested Resolution ID 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 Hash Map
		 */
		addDataElement(0x2020,0x0050, DicomConstants.DCM_DT_CS, enumRequestedResolutionID.getValue());
	}

	/**
	 * Return the resolution at which images in this Film Box are to be printed.
	 * 
	 * @return String - String value of Requested Resolution ID.
	 */
	public String getRequestedResolutionID()
	{
		Object objValue = getValue(0x2020,0x0050);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	
	/**
	 * Populates the query Model using filled dataset.
	 */
	public void populate(IDataSet objIDataSet)
	{
		super.populate(objIDataSet);
	}	
	
	/**
	 * Fills the dataset using already populated Query Model.
	 */
	public void fill(IDataSet objIDataSet)
	{
		super.fill(objIDataSet);
	}
}
