/*******************************************************************************
 *  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.services.javadbhelper;

import cdac.medinfo.sdk.dcm30_04.baselibs.ExplicitDE;
import cdac.medinfo.sdk.dcm30_04.baselibs.ImplicitDE;
import cdac.medinfo.sdk.dcm30_04.baselibs.SQ;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDataElement;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDataTypeSQ;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDictionaryReader;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IItem;
import cdac.medinfo.sdk.dcm30_04.commoninterface.ITransferSyntax;
import cdac.medinfo.sdk.dcm30_04.utils.DicomConstants;
import cdac.medinfo.sdk.dcm30_04.utils.IPairedCollection;
import cdac.medinfo.sdk.dcm30_04.utils.ISingleCollection;
import cdac.medinfo.sdk.dcm30_04.utils.PairedCollection;
import cdac.medinfo.sdk.dcm30_04.utils.SingleCollection;
import cdac.medinfo.sdk.dcm30_04.utils.StandardMethods;

/**
 * This class represents Item Model i.e. an item in a Sequence.
 * It contains the all the data elements of the item
 */
public class ItemModel
{
	private IPairedCollection<String, Object> objNameValuePair = new PairedCollection<String, Object>() ;
	private ISingleCollection<SQModel> objSQModelCollection = new SingleCollection<SQModel>();

	/**
	 * This method adds the attribute name and its value in the item model.
	 * The attribute name should be same as in the DICOM Data Dictionary.
	 * @param strAttributeName String value of attribute name
	 * @param strValue Value of the attribute
	 */
	public void addValue(String strAttributeName, Object strValue)
	{
		objNameValuePair.put(strAttributeName,strValue);
	}

	/**
	 * This method returns the Name/Value pair i.e. attributes and their values in the item.
	 * @return IPairedCollection<String, Object> Paired collection of attribute name and its value.
	 */
	public IPairedCollection<String, Object> getValue()
	{
		return objNameValuePair;
	}

	/**
	 * This method returns the SequenceModel for the Sequence data elements present in the item.
	 * @return ISingleCollection<SQModel> Sequence Model collection
	 */
	public ISingleCollection<SQModel> getSQModel()
	{
		return objSQModelCollection;
	}

	/**
	 * This method adds the sequence model in the item model. i.e. The sequence elements that is to be added in the item.
	 * @param objSqModel
	 */
	public void addSQModel(SQModel objSqModel)
	{
		objSQModelCollection.add(objSqModel);
	}

	/**
	 * This method populates the ItemModel from the item given.
	 * @param objIItem instance of item by which item model needs to be populated.
	 */
	public void populate(IItem objIItem)
	{
		IDictionaryReader objIDictionaryReader = objIItem.getDictionaryReader();
		for(IDataElement objIDataElement : objIItem)
		{
			String strVRFromDictionary = objIDictionaryReader.getVR(objIDataElement.getTag().getGroupNumber(), objIDataElement.getTag().getElementNumber());
			if(DicomConstants.DCM_DT_SQ == StandardMethods.getiVRtype(strVRFromDictionary))
			{
				String strSQName = objIDictionaryReader.getName(objIDataElement.getTag().getGroupNumber(), objIDataElement.getTag().getElementNumber());
				SQModel objSQModel = new SQModel(strSQName);
				objSQModel.populate((IDataTypeSQ)objIDataElement.getDicomValue());
				objSQModelCollection.add(objSQModel);
			}
			else
			{
				Object objValue = objIDataElement.getValue();
				String strAttributeName = objIDictionaryReader.getName(objIDataElement.getTag().getGroupNumber(), objIDataElement.getTag().getElementNumber());
				objNameValuePair.put(strAttributeName, objValue);
			}
		}
	}

	/**
	 * This method fill the Item from the populated item model.
	 * @param objIItem the instance of item which is to be filled from the item model
	 */
	public void fill(IItem objIItem)
	{
		IDictionaryReader objIDictionaryReader = objIItem.getDictionaryReader();
		Object[] strAttributeNames = objNameValuePair.getKeys();
		for(Object strAttributeName : strAttributeNames)
		{
			String strAttribute = (String)strAttributeName;
			short[] shTag = objIDictionaryReader.getTag(strAttribute);
			int iVR = StandardMethods.getiVRtype(objIDictionaryReader.getVR(shTag[0],shTag[1]));
			setValue(objNameValuePair.get(strAttribute), shTag[0], shTag[1], iVR, objIItem);
		}

		for(SQModel objSQModel : objSQModelCollection)
		{
			IDataTypeSQ objIDataTypeSQ = new SQ(objIItem.getTransferSyntax(),objIItem.getDictionaryReader());
			objSQModel.fill(objIDataTypeSQ);
			String strSQName = objSQModel.getSQName();
			short[] shTag = objIDictionaryReader.getTag(strSQName);
			int iVR = StandardMethods.getiVRtype(strSQName);
			setValue(objIDataTypeSQ.getValue(), shTag[0], shTag[1], iVR, objIItem);
		}
	}

	/**
	 * Sets value in dataElement and adds it to passed DataSet.
	 * @param objValue Object value 
	 * @param iGroupNumber Group Number of the DataElement
	 * @param iElementNumber Element Number of the DataElement
	 * @param iVR VR type for DataElement.
	 * @param objIDataSet instance of DataSet
	 */
	private void setValue(Object objValue,int iGroupNumber,int iElementNumber,int iVR,IItem objIItem)
	{
		/* 
		 * 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
		 */
		IDataElement objIDataElement = null;
		IDictionaryReader objIDictionaryReader = objIItem.getDictionaryReader();
		ITransferSyntax objITransferSyntax = objIItem.getTransferSyntax();

		if(objITransferSyntax.getVRTransferSyntax()==DicomConstants.DCM_VR_IMPLICIT)
			objIDataElement = new ImplicitDE(iGroupNumber,iElementNumber,objValue,objIDictionaryReader);
		else
			objIDataElement = new ExplicitDE(iGroupNumber,iElementNumber, iVR,objValue);
		objIItem.addDataElement(objIDataElement);
	}

	/**
	 * This method determines whether the item model is empty or not.
	 * @return boolean - returns true if the item model is empty else false is returned.
	 */
	public boolean isEmpty()
	{
		if(objNameValuePair.size()!=0)
		{
			return false;
		}
		else if(objSQModelCollection.size() !=0)
		{
			for(SQModel objSqModel : objSQModelCollection)
			{
				if(!objSqModel.isEmpty())
					return false;
			}
		}
		return true;
	}
}

