/*******************************************************************************
 *  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.PartialViewCodeSequence;
import cdac.medinfo.sdk.dcm30_04.baselibs.Tag;
import cdac.medinfo.sdk.dcm30_04.baselibs.ViewCodeSequence;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDataElement;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDataSet;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDicomValue;
import cdac.medinfo.sdk.dcm30_04.commoninterface.ITag;
import cdac.medinfo.sdk.dcm30_04.enums.EnumModality;
import cdac.medinfo.sdk.dcm30_04.enums.EnumBreastImplantPresent;
import cdac.medinfo.sdk.dcm30_04.enums.EnumPartialView;

import cdac.medinfo.sdk.dcm30_04.exceptions.ConditionFailedException;
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 is used for Breast View Module.
*/
public class BreastViewModule extends Module
{
	/**
	  * The obj single collection.
	  */
	 public static ISingleCollection<ITag> objSingleCollection = null;
		

		/**
		 * Instantiates a new BreastViewModule
		 * 
		 * @param objIDataSet the obj i data set
		 */
		public BreastViewModule(IDataSet objIDataSet)
		{
			super(objIDataSet);
		}

		static
		{
			objSingleCollection = new SingleCollection<ITag>();
			objSingleCollection.add(new Tag(0x0008,0x0008));
			objSingleCollection.add(new Tag(0x0054,0x0220));
			objSingleCollection.add(new Tag(0x0028, 0x1300));
			objSingleCollection.add(new Tag(0x0028, 0x1350));
			objSingleCollection.add(new Tag(0x0028, 0x1352));
		}

		/**
		 * 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
			{
				if(!isPresent(0x0008,0x0008))
					throw new MandatoryMissingException("0008,0008");
				if(!isPresent(0x0054,0x0220))
					throw new MandatoryMissingException("0054,0220");
				
				GeneralSeriesModule objGeneralSeriesModule = null;
				@SuppressWarnings("null")
				String strModality=objGeneralSeriesModule.getModality();
				if(strModality.equalsIgnoreCase(EnumModality.MG.getValue()) && !isPresent(0x0028,0x1300))
					throw new ConditionFailedException("0028,1300 is required if Modality (0008,0060) is MG.");
				
				String strPartialView=getPartialView();
				if(strPartialView.equalsIgnoreCase(EnumPartialView.YES.getValue()) && !isPresent(0x0028,0x1352))
					throw new ConditionFailedException("0028,1352 is required if Partial View (0028,1350) is present with a value of YES");
			}
			catch(MandatoryMissingException mme)
			{
				if(DicomConfig.createInstance().isLoggingOn())
					DicomLogger.getLogger().log(mme.getMessage());

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

			}
			catch(ConditionFailedException cfe)
			{
				if(DicomConfig.createInstance().isLoggingOn())
					DicomLogger.getLogger().log(cfe.getMessage());

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

			}
			return true;
			}
		/**
		 * Sets Image identification characteristics.
		 * 
		 * @param arrStrImageType - String array of Image identification characteristics.
		 */	
		public void setImageType(String[] arrStrImageType)
		{
			/*Accept Image identification characteristics in String Array format of type CS.
			 * 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(0x0008, 0x0008, DicomConstants.DCM_DT_CS, arrStrImageType);
		}

		/**
		 * Return Image Type.
		 * 
		 * @return String[]- String array of Image identification characteristics.
		 */
		public String[] getImageType()
		{
			if (objIDataSet == null)
				return null;
			IDataElement objIDataElement =  objIDataSet.getDataForTag(0x0008, 0x0008);
			if(objIDataElement == null)
				return null;
			IDicomValue objIDicomValue = objIDataElement.getDicomValue();
			if(objIDicomValue == null)
				return null;
			if(objIDicomValue.getValue()==null)
				return null;
			return (String[])objIDicomValue.getValue();
		}
		/**
		 * This method Returns provides the pre-initialized object of View Code Sequence return ViewCodeSequence - object of View Code 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 the View Code Sequence
		 */
		public ViewCodeSequence getViewCodeSequence()
		{
			ViewCodeSequence objViewCodeSequence = (ViewCodeSequence)getDicomValue(0x0054, 0x0220);
			if(objViewCodeSequence == 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();
				objViewCodeSequence = (ViewCodeSequence)objDicomV3Factory.createSequence(0x0054, 0x0220, objITransferSyntax, objIDictionaryReader);
				
				// This will add Data Element of SQ to the DataSet.
				addDataElement(0x0054, 0x0220, DicomConstants.DCM_DT_SQ, objViewCodeSequence.getValue());
			}
			return objViewCodeSequence;
		}
		
		/**
		 * Sets Whether or not the imaged breast contains a breast implant regardless of the visibility of a breast implant in the Pixel Data.
		 */	
		public void setBreastImplantPresent(EnumBreastImplantPresent enumBreastImplantPresent)
		{
			/*Accept the Breast Implant Present value 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 Hash Map
			 */
			addDataElement(0x0028, 0x1300, DicomConstants.DCM_DT_CS, enumBreastImplantPresent.getValue());
		}	

		/**
		 * Retrieves Whether or not the imaged breast contains a breast implant regardless of the visibility of a breast implant in the Pixel Data..
		 * @return String - String value of Breast Implant Present
		 */
		public String getBreastImplantPresent()
		{
			Object objValue = objIDataSet.getValue(0x0028, 0x1300);
			if(objValue != null)
				return objValue.toString();
			return null;
		}
		/**
		 * Sets whether this image is a partial view, that is a subset of a single view of the breast.
		 */	
		public void setPartialView(EnumPartialView enumPartialView)
		{
			/*Accept the Breast Implant Present value 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 Hash Map
			 */
			addDataElement(0x0028, 0x1350, DicomConstants.DCM_DT_CS, enumPartialView.getValue());
		}	

		/**
		 * Retrieves whether this image is a partial view, that is a subset of a single view of the breast.
		 * @return String - String value of Breast Implant Present
		 */
		public String getPartialView()
		{
			Object objValue = objIDataSet.getValue(0x0028, 0x1350);
			if(objValue != null)
				return objValue.toString();
			return null;
		}
		/**
		 * This method Returns provides the pre-initialized object of Partial View Code Sequence return PartialViewCodeSequence - object of View Code 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 the Partial View Code Sequence
		 */
		public PartialViewCodeSequence getPartialViewCodeSequence()
		{
			PartialViewCodeSequence objPartialViewCodeSequence = (PartialViewCodeSequence)getDicomValue(0x0028, 0x1352);
			if(objPartialViewCodeSequence == 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();
				objPartialViewCodeSequence = (PartialViewCodeSequence)objDicomV3Factory.createSequence(0x0028, 0x1352, objITransferSyntax, objIDictionaryReader);
				
				// This will add Data Element of SQ to the DataSet.
				addDataElement(0x0028, 0x1352, DicomConstants.DCM_DT_SQ, objPartialViewCodeSequence.getValue());
			}
			return objPartialViewCodeSequence;
		}
		/**
		 * 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;
		}
}
