/*******************************************************************************
 *  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.IDicomValue;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDictionaryReader;
import cdac.medinfo.sdk.dcm30_04.commoninterface.ITransferSyntax;
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 provides methods to set,get and validate attributes in {@link ReferencedBeamSequence}
 */

public class ReferencedBeamSequenceItem extends Item  
{
	


	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

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

	/*
	 * This constructor calls the respective superclass constructor
	 * This constructor should throw exception if null TS is tried to be set
	 */
	/**
	 * This constructor creates the item and internal code sequence macro with default TransferSyntax.
	 * @param objTransferSyntax specifies the DICOM Standard defined TransfeSyntax 
	 */
	ReferencedBeamSequenceItem(ITransferSyntax objITransferSyntax)
	{
		super(objITransferSyntax);
	}

	/**
	 * This constructor creates ReferencedBeamSequenceItem with specified TransferSyntax and
	 * specified DictionaryReader
	 * @param objTransferSyntax specifies the DICOM Standard defined TransfeSyntax
	 * @param objDictionaryReader specifies the DICOM Dictionary reader to be used 
	 */
	ReferencedBeamSequenceItem(ITransferSyntax objTransferSyntax, IDictionaryReader objDictionaryReader)
	{
		super(objTransferSyntax,objDictionaryReader);
	}

	/**
	 * Validates all the attributes in ReferencedBeamSequenceItem that are present in the DataSet
	 * @return boolean - Success -true, Failure - false
	 * @throws InvalidItemException throws InvalidItemException If Mandatory or Conditional element fails.
	 */
	public boolean validateForModule()  throws InvalidItemException
	{
		try{
			super.validateForModule();
			if(!contains(0x300C,0x0006))
				throw new MandatoryMissingException("300C,0006");

		}
		catch(MandatoryMissingException mme)
		{
			if(DicomConfig.createInstance().isLoggingOn())
			{
				DicomLogger.getLogger().log(mme.getMessage());
			}
			throw new InvalidItemException(this.getClass().getSimpleName(),mme);
		}
		return true;
	}

	/**
	 * Sets References Beam specified by Beam Number (300A,00C0) in Beam Sequence (300A,00B0) in RT Beams Module within referenced RT Plan.
	 * @param strReferencedBeamNumber String value of Referenced Beam Number.
	 */
	public void setReferencedBeamNumber(String strReferencedBeamNumber)
	{
		/*Accept the ReferencedBeamNumber 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
		 */
		IDataElement objIDataElement = null;
		if(objITransferSyntax.getVRTransferSyntax() == DicomConstants.DCM_VR_IMPLICIT)
			objIDataElement = new ImplicitDE(0x300C,0x0006, strReferencedBeamNumber,getDictionaryReader());
		else
			objIDataElement = new ExplicitDE(0x300C,0x0006,DicomConstants.DCM_DT_IS, strReferencedBeamNumber);

		addDataElement(objIDataElement);
	}

	/**
	 * Retrieves Referenced Beam Number.
	 * @return String - value of Referenced Beam Number
	 */
	public String getReferencedBeamNumber()
	{
		Object objValue = getValue(0x300C,0x0006);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Sets coordinates (x,y,z) of point at which Beam Dose is specified in the patient based coordinate system.
	 * @param arrStrBeamDoseSpecificationPoint String value of Beam Dose Specification Point.
	 */
	public void setBeamDoseSpecificationPoint(String[] arrStrBeamDoseSpecificationPoint)
	{
		/*Accept the Beam Dose Specification Point 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 Data Set
		 */
		IDataElement objIDataElement = null;
		if(objITransferSyntax.getVRTransferSyntax() == DicomConstants.DCM_VR_IMPLICIT)
			objIDataElement = new ImplicitDE(0x300A,0x0082, arrStrBeamDoseSpecificationPoint,getDictionaryReader());
		else
			objIDataElement = new ExplicitDE(0x300A,0x0082,DicomConstants.DCM_DT_DS, arrStrBeamDoseSpecificationPoint);

		addDataElement(objIDataElement);
	}

	/**
	 * Retrieves coordinates (x,y,z) of point at which Beam Dose is specified in the patient based coordinate system.
	 * @return String - value of Beam Dose Specification Point.
	 */
	public String[] getBeamDoseSpecificationPoint()
	{
		Object objValue = getValue(0x300A,0x0082);
		if(objValue != null)
			return (String[])objValue;
		return null;
	}


	/**
	 * Sets dose (in Gy) at Beam Dose Specification Point (300A,0082) due to current Beam.
	 * @param strBeamDose String value of Beam Dose.
	 */
	public void setBeamDose(String strBeamDose)
	{
		/*Accept the Beam Dose 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 Data Set
		 */
		IDataElement objIDataElement = null;
		if(objITransferSyntax.getVRTransferSyntax() == DicomConstants.DCM_VR_IMPLICIT)
			objIDataElement = new ImplicitDE(0x300A,0x0084, strBeamDose,getDictionaryReader());
		else
			objIDataElement = new ExplicitDE(0x300A,0x0084,DicomConstants.DCM_DT_DS, strBeamDose);

		addDataElement(objIDataElement);
	}

	/**
	 * Retrieves dose (in Gy) at Beam Dose Specification Point (300A,0082) due to current Beam.
	 * @return String - value of Beam Dose.
	 */
	public String getBeamDose()
	{
		Object objValue = getValue(0x300A,0x0084);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Sets machine setting to be delivered for current Beam, specified in Monitor Units (MU) or
	 * minutes as defined by Primary Dosimeter Unit (300A,00B3) (in RT Beams Module) for referenced Beam.
	 * @param strBeamMeterset String value of Beam Meterset.
	 */
	public void setBeamMeterset(String strBeamMeterset)
	{
		/*Accept the Beam Meterset 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 Data Set
		 */
		IDataElement objIDataElement = null;
		if(objITransferSyntax.getVRTransferSyntax() == DicomConstants.DCM_VR_IMPLICIT)
			objIDataElement = new ImplicitDE(0x300A,0x0086, strBeamMeterset,getDictionaryReader());
		else	
			objIDataElement = new ExplicitDE(0x300A,0x0086,DicomConstants.DCM_DT_DS, strBeamMeterset);

		addDataElement(objIDataElement);
	}

	/**
	 * Retrieves machine setting to be delivered for current Beam, specified in Monitor Units (MU) or
	 * minutes as defined by Primary Dosimeter Unit (300A,00B3) (in RT Beams Module) for referenced Beam.
	 * @return String - value of Beam Meterset.
	 */
	public String getBeamMeterset()
	{
		Object objValue = getValue(0x300A,0x0086);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	
	/**
	 * Retrieves pre-initialized object of Beam Dose VerificationControl Point 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 BeamDoseVerificationControlPointSequence - instance of Beam Dose VerificationControl Point Sequence. 
	 */
	public BeamDoseVerificationControlPointSequence getBeamDoseVerificationControlPointSequence()
	{
		BeamDoseVerificationControlPointSequence objBeamDoseVerificationControlPointSequence = null;
		IDataElement objIDataElement =  getDataForTag(0x300A, 0x008C); //getDataElement
		if(objIDataElement != null)
		{
			IDicomValue objIDicomValue = objIDataElement.getDicomValue();
			if(objIDicomValue != null)
				objBeamDoseVerificationControlPointSequence = (BeamDoseVerificationControlPointSequence)objIDicomValue;
		}
		else
		{
			DicomV3Factory objDicomV3Factory = DicomV3Factory.createInstance();
			int iVRTransferSyntax = objITransferSyntax.getVRTransferSyntax();
			objIDataElement = null;
			objBeamDoseVerificationControlPointSequence = (BeamDoseVerificationControlPointSequence)objDicomV3Factory.createSequence(0x300A, 0x008C, objITransferSyntax, objIDictionaryReader);

			if(iVRTransferSyntax == DicomConstants.DCM_VR_IMPLICIT)
				objIDataElement = new ImplicitDE(0x300A, 0x008C, objBeamDoseVerificationControlPointSequence.getValue(), objIDictionaryReader);
			else
				objIDataElement = new ExplicitDE(0x300A, 0x008C, DicomConstants.DCM_DT_SQ, objBeamDoseVerificationControlPointSequence.getValue());
			objIDataElement.setTransferSyntax(objITransferSyntax);
			if(objIDataElement != null)
				addDataElement(objIDataElement);
		}
		return objBeamDoseVerificationControlPointSequence;
	}
}
