/*******************************************************************************
 *  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.ConditionFailedException;
import cdac.medinfo.sdk.dcm30_04.exceptions.InvalidModuleException;
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;

// TODO: Auto-generated Javadoc
/**
 \* This module contains IOD Attributes that may be the target of the Frame Increment Pointer (0028,0009) for SC Multi-frame images.
 */
public class SCMultiFrameVectorModule extends Module  
{


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


	/**
	 * Instantiates a new sC multi frame vector module.
	 * 
	 * @param objIDataSet the obj i data set
	 */
	public SCMultiFrameVectorModule(IDataSet objIDataSet)
	{
		super(objIDataSet);
	}
	static
	{
		objSingleCollection = new SingleCollection<ITag>();
		objSingleCollection.add(new Tag(0x0018,0x1065));
		objSingleCollection.add(new Tag(0x0018,0x2001));
		objSingleCollection.add(new Tag(0x0018,0x2002));
		objSingleCollection.add(new Tag(0x0018,0x2003));
		objSingleCollection.add(new Tag(0x0018,0x2004));
		objSingleCollection.add(new Tag(0x0018,0x2005));
		objSingleCollection.add(new Tag(0x0018,0x2006));
	}

	/**
	 * 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 boolean - returns validation status as success or failure
	 * 
	 * @throws InvalidModuleException - If validation of Module fails
	 */	

	public  boolean validateModule() throws InvalidModuleException
	{

		try
		{			
			MultiFrameModule objMultiFrameModule = new MultiFrameModule(objIDataSet);
			/*
			 * Attribute FrameIncrementPointer contains collection of tags.
			 * Condition :- if Frame Increment Pointer(0028,0009) points to Frame Time Vector(0018,1065).
			 * If Frame Increment Pointer collection contains this tag then meaning has been taken as referred.
			 * same for other attributes.
			 * refer pdf 3 page 414.
			 */
			ISingleCollection<ITag> objISingleCollection = objMultiFrameModule.getFrameIncrementPointer();
			ITag objITagFrameTimeVector = new Tag(0x0018,0x1065);
			ITag objITagPageNumberVector = new Tag(0x0018,0x2001);
			ITag objITagFrameLabelVector = new Tag(0x0018,0x2002);
			ITag objITagFramePrimaryAngleVector = new Tag(0x0018,0x2003);
			ITag objITagFrameSecondaryAngleVector = new Tag(0x0018,0x2004);
			ITag objITagSliceLocationVector = new Tag(0x0018,0x2005);
			ITag objITagDisplayWindowLabelVector = new Tag(0x0018,0x2006);

			if(objISingleCollection != null)
			{
				if(objISingleCollection.contains(objITagFrameTimeVector) && (!isPresent(0x0018,0x1065)))
					throw new ConditionFailedException("0018,1065 Required if Frame Increment Pointer (0028,0009) points to Frame Time Vector ");
				if(objISingleCollection.contains(objITagPageNumberVector)&&(!isPresent(0x0018, 0x0018)))
					throw new ConditionFailedException("0018,2001 Required if Frame Increment Pointer (0028,0009) points to Page Number Vector ");
				if(objISingleCollection.contains(objITagFrameLabelVector)&&(!isPresent(0x0018, 0x2002)))
					throw new ConditionFailedException("0018,2002 Required if Frame Increment Pointer (0028,0009) points to Frame Label Vector");
				if(objISingleCollection.contains(objITagFramePrimaryAngleVector)&&(!isPresent(0x0018, 0x2003)))
					throw new ConditionFailedException("0018,2003 Required if Frame Increment Pointer (0028,0009) points to Frame Primary Angle Vector (0018,2003).");
				if(objISingleCollection.contains(objITagFrameSecondaryAngleVector) && (!isPresent(0x0018, 0x2004)))
					throw new ConditionFailedException("0018,2004 Required if Frame Increment Pointer (0028,0009) points to Frame Secondary Angle Vector (0018,2004).");
				if(objISingleCollection.contains(objITagSliceLocationVector)&& (!isPresent(0x0018, 0x2005)))
					throw new ConditionFailedException("0018,2005 Required if Frame Increment Pointer (0028,0009) points to Slice Location Vector");
				if(objISingleCollection.contains(objITagDisplayWindowLabelVector))
					throw new ConditionFailedException(" 0018,2006 Required if Frame Increment Pointer (0028,0009) points to Display Window Label Vector");
			}
		}
		catch(ConditionFailedException cfe)
		{
			if(DicomConfig.createInstance().isLoggingOn())
				DicomLogger.getLogger().log(cfe.getMessage());

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

		}
		return true;
	}

	/**
	 * Sets an array that contains the real time increments (in msec) between frames for
	 * a Multi-frame image. Required if Frame Increment Pointer (0028,0009) points to
	 * Frame Time Vector.
	 * 
	 * @param arrStrFrameTimeVector - String array of Frame Time values.
	 */
	public void setFrameTimeVector(String[] arrStrFrameTimeVector)
	{
		/* Accept Frame Time in String format.
		 * 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, 0x1063, DicomConstants.DCM_DT_DS, arrStrFrameTimeVector);
	}

	/**
	 * Retrieves An array that contains the real time increments (in msec) between frames for
	 * a Multi-frame image.
	 * 
	 * @return String[] - String array of Frame Time values.
	 */
	public String[] getFrameTimeVector()
	{Object objectValue = getValue(0x0018,0x1065);
		if(objectValue!=null)
			return (String[])objectValue;
		return null;
	}


	/**
	 * Sets an array which contains, for each of the image frames, the corresponding page numbers of the original document.
	 * 
	 * @param arrStrPageNumberVector - String array of Page Number Vector.
	 */
	public void setPageNumberVector(String[] arrStrPageNumberVector)
	{
		/*Accept Page Number Vectorin Array of String format of type IS.
		 * 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
		 */
		addDataElement(0x0018,0x2001, DicomConstants.DCM_DT_IS, arrStrPageNumberVector);
	}

	/**
	 * Retrieves an array which contains, for each of the image frames, the corresponding page numbers of the original document.
	 * 
	 * @return String[] - String array of Page Number Vector.
	 */
	public String[] getPageNumberVector()
	{Object objectValue = getValue(0x0018,0x2001);
		if(objectValue!=null)
			return (String[])objectValue;
		return null;
	}

	/**
	 * Sets a multi-valued attribute that contains a descriptive label for each of the image
	 * frames.
	 * 
	 * @param arrStrFrameLabelVector the arr str frame label vector
	 */
	public void setFrameLabelVector(String[] arrStrFrameLabelVector)
	{
		/*Accept Frame Label Vector in Array of String format of type SH.
		 * 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, 0x2002, DicomConstants.DCM_DT_SH, arrStrFrameLabelVector);
	}

	/**
	 * Return multi-valued attribute that contains a descriptive label for each of the image.
	 * 
	 * @return String[] - String Array of String array of FrameLabelVector
	 */
	public String[] getFrameLabelVector()
	{
		Object objectValue = getValue(0x0018, 0x2002);
		if(objectValue!=null)
			return (String[])objectValue;
		return null;
	}

	/**
	 * Sets an array for each of the image frames, the primary angle of rotation about an undefined axis,
	 * in degrees. May be used for annotative purposes for cine loops of 3D reprojected images.
	 * 
	 * @param arrStrFramePrimaryAngleVector - String array of Frame Primary Angle Vector.
	 */
	public void setFramePrimaryAngleVector(String[] arrStrFramePrimaryAngleVector)
	{
		/*Accept Frame Primary Angle Vector in Array of 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 Data Set
		 */
		addDataElement(0x0018,0x2003, DicomConstants.DCM_DT_DS, arrStrFramePrimaryAngleVector);
	}

	/**
	 * Retrieves an array for each of the image frames, the primary angle of rotation about an undefined axis,in degrees.
	 * 
	 * @return String[] - String array of Frame Primary Angle Vector.
	 */
	public String[] getFramePrimaryAngleVector()
	{Object objectValue = getValue(0x0018,0x2003);
		if(objectValue!=null)
			return (String[])objectValue;
		return null;
	}

	/**
	 * Sets an array for each of the image frames, the secondary angle of rotation about an undefined axis,
	 * i.e. orthogonal to that used for Frame Primary Angle Vector (0018,2003), in degrees. May be used for annotative purposes for cine loops of 3D reprojected images.
	 * 
	 * @param arrStrFrameSecondaryAngleVector - String array of Frame Secondary Angle Vector.
	 */
	public void setFrameSecondaryAngleVector(String[] arrStrFrameSecondaryAngleVector)
	{
		/*Accept Frame Secondary Angle Vector in Array of 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 Data Set
		 */
		addDataElement(0x0018,0x2004, DicomConstants.DCM_DT_DS, arrStrFrameSecondaryAngleVector);
	}

	/**
	 * Retrieves an array for each of the image frames, the secondary angle of rotation about an undefined axis,in degrees.
	 * 
	 * @return String[] - String array of Frame secondary Angle Vector.
	 */
	public String[] getFrameSecondaryAngleVector()
	{Object objectValue = getValue(0x0018,0x2004);
		if(objectValue!=null)
			return (String[])objectValue;
		return null;
	}


	/**
	 * Sets Relative position of exposure expressed in mm, as defined for Slice Location (0020,1041).
	 * 
	 * @param arrStrSliceLocationVector - String array of Slice Location Vector.
	 */
	public void setSliceLocationVector(String[] arrStrSliceLocationVector)
	{
		/*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, arrStrSliceLocationVector);
	}

	/**
	 * Retrieves Relative position of exposure expressed in mm, as defined for Slice Location (0020,1041).
	 * 
	 * @return String[] - String array of Slice Location Vector.
	 */
	public String[] getSliceLocationVector()
	{Object objectValue = getValue(0x0018,0x2005);
		if(objectValue!=null)
			return (String[])objectValue;
		return null;
	}


	/**
	 * Sets An array which contains, for each of the image frames, a label or number of the  display window of a graphical user
	 * interface from which the frame was captured.
	 * 
	 * @param arrStrDisplayWindowLabelVector - String array of Display Window Label Vector.
	 */
	public void setDisplayWindowLabelVector(String[] arrStrDisplayWindowLabelVector)
	{
		/*Accept Display Window Label Vector in Array of String format of type SH.
		 * 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
		 */
		addDataElement(0x0018,0x2006, DicomConstants.DCM_DT_SH, arrStrDisplayWindowLabelVector);
	}

	/**
	 * Retrieves  An array which contains, for each of the image frames, a label or number of the  display window of a graphical user
	 * interface from which the frame was captured.
	 * 
	 * @return String[] - String array of Display Window Label Vector.
	 */
	public String[] getDisplayWindowLabelVector()
	{Object objectValue = getValue(0x0018,0x2006);
		if(objectValue!=null)
			return (String[])objectValue;
		return null;
	}

	/**
	 * This method returns the vector of keys representing the DataElements
	 * that belong to this module.
	 * 
	 * @return vector of Tags - returns the vector containing the collection of tags.
	 */
	public ISingleCollection<ITag> getVectorOfKeys()
	{
		return objSingleCollection;
	}
}
