/*******************************************************************************
 *  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.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 Class is specifies the Attributes that define the transmitted pixel array of a two dimensional
 * image plane.
 * 
 * 
 */
public class ImagePlaneModule extends Module  
{


	/**
	 * The obj single collection.
	 */
	public static ISingleCollection<ITag> objSingleCollection = null;


	/**
	 * Creates Image Plane Module with defaultinitialization.
	 * 
	 * @param objIDataSet the obj i data set
	 */
	public ImagePlaneModule(IDataSet objIDataSet)
	{
		super(objIDataSet);
	}

	static
	{
		objSingleCollection = new SingleCollection<ITag>();
		objSingleCollection.add(new Tag(0x0018,0x0050));

		objSingleCollection.add(new Tag(0x0020,0x0032));
		objSingleCollection.add(new Tag(0x0020,0x0037));
		objSingleCollection.add(new Tag(0x0020,0x1041));

		objSingleCollection.add(new Tag(0x0028,0x0030));
	}

	/**
	 * 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 true, if validate module
	 * 
	 * @throws InvalidModuleException - If validation of Module fails
	 */

	public boolean validateModule()throws InvalidModuleException
	{

		try
		{
			/*
			 * Validation Rules for Mandatory Elements
			 */
			if(!isPresent(0x0028,0x0030))
				throw new MandatoryMissingException("Missing Mandatory Element 0028,0030");
			else if(!isPresent(0x0020,0x0037))
				throw new MandatoryMissingException("Missing Mandatory Element 0028,0037");
			else if(!isPresent(0x0020,0x0032))
				throw new MandatoryMissingException("Missing Mandatory Element 0028,0032");
			else if(!isPresent(0x0018,0x0050))
				throw new MandatoryMissingException("Missing Mandatory Element 0028,0050");
		}
		catch(MandatoryMissingException mme)
		{
			if(DicomConfig.createInstance().isLoggingOn())
				DicomLogger.getLogger().log(mme.getMessage());

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

		}
		return true;
	}

	/**
	 * This method is used to set physical distance in the patient between the center of each pixel, specified by a
	 * numeric pair - adjacent row spacing (delimiter) adjacent column spacing in mm.
	 * The function accepts a String Value and creates the
	 * DE based on the transfer syntax and populates the DE with right values.
	 * This De is then added to the Module HashMap
	 * 
	 * @param arrStrPixelSpacing :physical distances in the patient between the center of each pixel.
	 */	
	public void setPixelSpacing(String[] arrStrPixelSpacing)
	{
		/*Accept the direction cosines of the first row and the first column with respect
		 *to the patient in String Array format of type DS.
		 * Read the Transfer Syntax and check to create ImplicitDE or ExplicitDE .
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0028, 0x0030, DicomConstants.DCM_DT_DS, arrStrPixelSpacing);
	}

	/**
	 * This method is used to set the direction cosines of the first row and the first column with respect
	 * to the patient.
	 * The function accepts a String Value and creates the
	 * DE based on the transfer syntax and populates the DE with right values.
	 * This De is then added to the Module HashMap
	 * 
	 * @param arrStrImageOrientationPatient :the direction cosines of the first row and the first column with respect
	 * to the patient.
	 */	
	public void setImageOrientationPatient(String[] arrStrImageOrientationPatient)
	{
		/*Accept  the direction cosines of the first row and the first column with respect
		 *  to the patient in String Array format of type DS.
		 * Read the Transfer Syntax and check to create ImplicitDE or ExplicitDE .
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0020, 0x0037, DicomConstants.DCM_DT_DS, arrStrImageOrientationPatient);
	}

	/**
	 * This method is used to set the x, y, and z coordinates of the upper left hand corner
	 * (center of the first voxel transmitted) of the image, in mm.
	 * The function accepts a String Value and creates the
	 * DE based on the transfer syntax and populates the DE with right values.
	 * This De is then added to the Module HashMap
	 * 
	 * @param arrStrImagePositionPatient :Specifies the x, y, and z coordinates of the upper left hand corner
	 * (center of the first voxel transmitted) of the image, in mm.
	 * to the patient.
	 */	
	public void setImagePositionPatient(String[] arrStrImagePositionPatient)
	{
		/*Accept  Nthe x, y, and z coordinates of the upper left hand corner 
		 * (center of the first voxel transmitted) of the image, in mm in String Array format of type DS.
		 * Read the Transfer Syntax and check to create ImplicitDE or ExplicitDE .
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0020, 0x0032, DicomConstants.DCM_DT_DS, arrStrImagePositionPatient);
	}

	/**
	 * The method is used to set Nominal slice thickness, in mm.
	 * The function accepts a String Value as the strStudyInstanceUID and creates the
	 * DE based on the transfer syntax and populates the DE with right values.
	 * This De is then added to the Module HashMap
	 * 
	 * @param strSliceThickness : nominal slice thickness, in mm.
	 */
	public void setSliceThickness(String strSliceThickness)
	{
		/*Accept Nominal slice thickness, in mm in String format of type DS.
		 * 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(0x0018, 0x0050, DicomConstants.DCM_DT_DS, strSliceThickness);
	}

	/**
	 * The method is used to set Relative position of exposure expressed in mm.
	 * The function accepts a String Value as the strStudyInstanceUID and creates the
	 * DE based on the transfer syntax and populates the DE with right values.
	 * This De is then added to the Module HashMap
	 * 
	 * @param strSliceLocation : relative position of exposure expressed in mm.
	 */
	public void setSliceLocation(String strSliceLocation)
	{
		/*Accept Relative position of exposure expressed in mm.in String format of type DS.
		 * 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(0x0020,0x1041, DicomConstants.DCM_DT_DS, strSliceLocation);
	}

	/**
	 * Retrieves the specing between pixels.
	 * 
	 * @return String[] - returna the spacing between pixels
	 */
	public String[] getPixelSpacing()
	{
		Object objValue = getValue(0x0028, 0x0030);
		if(objValue != null)
		{
			return (String[])objValue;
		}
		return null;
	}

	/**
	 * Retrieves the Patient Image Orientation.
	 * 
	 * @return String[] - returns the patient image orientation
	 */
	public String[] getImageOrientationPatient()
	{
		Object objValue = getValue(0x0020, 0x0037);
		if(objValue != null)
		{
			return (String[])objValue;
		}
		return null;
	}

	/**
	 * Retrieves the Patient Image Position.
	 * 
	 * @return String[] - returns the patient image position
	 */
	public String[] getImagePositionPatient()
	{
		Object objValue = getValue(0x0020, 0x0032);
		if(objValue != null)
		{
			return (String[])objValue;
		}
		return null;
	}

	/**
	 * Retrieves the slice thickness.
	 * 
	 * @return String - returns the slice thickness
	 */
	public String getSliceThickness()
	{
		Object objValue = getValue(0x0018, 0x0050);
		if(objValue != null)
		{
			return (String)objValue;
		}
		return null;
	}

	/**
	 * Retrieves the slice location.
	 * 
	 * @return String - returns the slice location
	 */
	public String getSliceLocation()
	{
		Object objValue = getValue(0x0020, 0x1041);
		if(objValue != null)
		{
			return (String)objValue;
		}
		return null;
	}


	/**
	 * This method returns the custom collection containing the list of DataElements belonging to the CT
	 * Image Module specified by DICOM Standard.
	 * 
	 * @return collection - custom collection containing the list of DataElements belonging to the CT Image Module
	 */
	public ISingleCollection<ITag> getVectorOfKeys()
	{
		return objSingleCollection;
	}
}
