/*******************************************************************************
 *  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.DicomV3Factory;
import cdac.medinfo.sdk.dcm30_04.baselibs.FailedParametersSequence;
import cdac.medinfo.sdk.dcm30_04.baselibs.GeneralMachineVerificationSequence;
import cdac.medinfo.sdk.dcm30_04.baselibs.OverriddenParametersSequence;
import cdac.medinfo.sdk.dcm30_04.baselibs.ReferencedRTPlanSequence;
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.enums.EnumTreatmentVerificationStatus;

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 module specifies the attributes of RT General Machine Verification Module.
 */
public class RTGeneralMachineVerificationModule extends Module
{
	/**
	 * The obj single collection.
	 */
	public static ISingleCollection<ITag> objSingleCollection = null;


	/**
	 * Creates RTGeneralMachineVerificationModule with default initialization.
	 * 
	 * @param objIDataSet the obj i data set
	 */
	public RTGeneralMachineVerificationModule(IDataSet objIDataSet)
	{
		super(objIDataSet);
	}

	static
	{
		objSingleCollection = new SingleCollection<ITag>();
		objSingleCollection.add(new Tag(0x300C,0x0002));
		objSingleCollection.add(new Tag(0x300C,0x0022));
		objSingleCollection.add(new Tag(0x0010,0x0020));
		objSingleCollection.add(new Tag(0x3008,0x002C));
		objSingleCollection.add(new Tag(0x0074,0x1048));
		objSingleCollection.add(new Tag(0x0074,0x104A));
	}

	/**
	 * 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
		{
			/*
			 * Validation Rules for Mandatory Elements
			 */

		}
		catch(MandatoryMissingException mme)
		{
			if(DicomConfig.createInstance().isLoggingOn())
				DicomLogger.getLogger().log(mme.getMessage());

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

		}
		return true;
	}
	
	
	/**
	 * Retrieves pre-initialized object of Referenced RT Plan Sequence. If the module contains the sequence object
	 * it returns the same otherwise it creates the sequence adds to the module with proper initialization
	 * and then returns the object of sequence
	 * 
	 * @return ReferencedRTPlanSequence - instance of ReferencedRTPlanSequence.
	 */
	public ReferencedRTPlanSequence getReferencedRTPlanSequence()
	{
		ReferencedRTPlanSequence objReferencedRTPlanSequence = (ReferencedRTPlanSequence)getDicomValue(0x300C,0x0002);
		if(objReferencedRTPlanSequence == 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.
			 */
			DicomV3Factory objDicomV3Factory = DicomV3Factory.createInstance();
			objReferencedRTPlanSequence = (ReferencedRTPlanSequence)objDicomV3Factory.createSequence(0x300C,0x0002, objITransferSyntax, objIDictionaryReader);
			
			// This will add Data Element of SQ to the DataSet.
			addDataElement(0x300C,0x0002, DicomConstants.DCM_DT_SQ, objReferencedRTPlanSequence.getValue());
		}
		return objReferencedRTPlanSequence;
	}
	
	/**
	 * Sets Identifier of Fraction Group within referenced RT Plan.
	 * @param strReferencedFractionGroupNumber String value of Identifier of Fraction Group within referenced RT Plan.
	 */
	public void setReferencedFractionGroupNumber (String strReferencedFractionGroupNumber )
	{
		/*Accept the Referenced Reference Image Number  in 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(0x300C,0x0022, DicomConstants.DCM_DT_IS,strReferencedFractionGroupNumber);
	}
	/**
	 * Retrieves Identifier of Fraction Group within referenced RT Plan.
	 * @return String - value of Identifier of Fraction Group within referenced RT Plan.
	 */
	public String getReferencedFractionGroupNumber()
	{
		Object objValue = getValue(0x300C,0x0022);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	/**
	 * Sets Primary hospital identification number or code for the patient.
	 * @param strPatientID String value of Primary hospital identification number or code for the patient.
	 */
	public void setPatientID(String strPatientID)
	{
		/* Accept the PatientID in String format of type LO.
		 * 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(0x0010,0x0020, DicomConstants.DCM_DT_LO,strPatientID);
	}

	/**
	 * Return Primary hospital identification number or code for the patient.
	 * @return String - value of Primary hospital identification number or code for the patient.
	 */
	public String getPatientID()
	{
		Object objValue = getValue(0x0010,0x0020);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	/**
	 * Sets conditions under which treatment was verified by a verification system.
	 *Enumerated Values:
	 *VERIFIED:treatment verified
	 *VERIFIED_OVR:treatment verified with at least one out-of-rangevalue overridden
	 *NOT_VERIFIED:treatment failed verification (one or more valuesout of range and not overridden)
	 * @param enumTreatmentVerificationStatus enum value of Treatment Verification Status
	 */
	public void setTreatmentVerificationStatus(EnumTreatmentVerificationStatus enumTreatmentVerificationStatus)
	{
		/* Accept the Treatment VerificationS tatus 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
		 */
		addDataElement(0x3008,0x002C, DicomConstants.DCM_DT_CS,enumTreatmentVerificationStatus);
	}
	/**
	 * Returns Treatment Verification Status 
	 * @return String - value of TreatmentVerificationStatus.
	 */
	public String getTreatmentVerificationStatus()
	{
		Object objValue = getValue(0x3008,0x002C);
		if(objValue != null)
			return objValue.toString();
		return null;
	}


	/**
	 * Retrieves pre-initialized object of Failed Parameters Sequence. If the module contains the sequence object it returns the same otherwise it creates the sequence adds to the module with proper initialization and then returns the object of sequence
	 * @return FailedAttributesSequence - instance of Failed Parameters Sequence.
	 */
	public FailedParametersSequence getFailedParametersSequence()
	{
		FailedParametersSequence objFailedParametersSequence = (FailedParametersSequence)getDicomValue(0x0074,0x1048);
		if(objFailedParametersSequence == 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.
			 */
			DicomV3Factory objDicomV3Factory = DicomV3Factory.createInstance();
			objFailedParametersSequence = (FailedParametersSequence)objDicomV3Factory.createSequence(0x0074,0x1048, objITransferSyntax, objIDictionaryReader);
			
			// This will add Data Element of SQ to the DataSet.
			addDataElement(0x0074,0x1048, DicomConstants.DCM_DT_SQ, objFailedParametersSequence.getValue());
		}
		return objFailedParametersSequence;
	}
	

	/**
	 * Retrieves pre-initialized object of Overridden Parameters Sequence. If the module contains the sequence object it returns the same otherwise it creates the sequence adds to the module with proper initialization and then returns the object of sequence
	 * @return OverriddenParametersSequence - instance of Overridden Parameters Sequence.
	 */
	public OverriddenParametersSequence getOverriddenParametersSequence()
	{
		OverriddenParametersSequence objOverriddenParametersSequence = (OverriddenParametersSequence)getDicomValue(0x0074,0x104A);
		if(objOverriddenParametersSequence == 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.
			 */
			DicomV3Factory objDicomV3Factory = DicomV3Factory.createInstance();
			objOverriddenParametersSequence = (OverriddenParametersSequence)objDicomV3Factory.createSequence(0x0074,0x104A, objITransferSyntax, objIDictionaryReader);
			
			// This will add Data Element of SQ to the DataSet.
			addDataElement(0x0074,0x104A, DicomConstants.DCM_DT_SQ, objOverriddenParametersSequence.getValue());
		}
		return objOverriddenParametersSequence;
	}
	/**
	 * Retrieves pre-initialized object of General Machine Verification Sequence. If the module contains the sequence object it returns the same otherwise it creates the sequence adds to the module with proper initialization and then returns the object of sequence
	 * @return GeneralMachineVerificationSequence - instance of General Machine Verification Sequence.
	 */
	public GeneralMachineVerificationSequence getGeneralMachineVerificationSequence()
	{
		GeneralMachineVerificationSequence objGeneralMachineVerificationSequence = (GeneralMachineVerificationSequence)getDicomValue(0x0074,0x1042);
		if(objGeneralMachineVerificationSequence == null)
		{

			DicomV3Factory objDicomV3Factory = DicomV3Factory.createInstance();
			objGeneralMachineVerificationSequence = (GeneralMachineVerificationSequence)objDicomV3Factory.createSequence(0x0074,0x1042, objITransferSyntax, objIDictionaryReader);
			
			// This will add Data Element of SQ to the DataSet.
			addDataElement(0x0074,0x1042, DicomConstants.DCM_DT_SQ, objGeneralMachineVerificationSequence.getValue());
		}
		return objGeneralMachineVerificationSequence;
	}
	
	/**
	 * 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;
	}
}
