/*******************************************************************************
 *  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.print.printsinkimpl;

import java.io.IOException;
import java.sql.SQLException;
import java.util.Locale;

import cdac.medinfo.sdk.dcm30_04.baselibs.DataSet;
import cdac.medinfo.sdk.dcm30_04.baselibs.ExplicitDE;
import cdac.medinfo.sdk.dcm30_04.baselibs.ImplicitDE;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDataElement;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDataSet;
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.enums.EnumCommandField;
import cdac.medinfo.sdk.dcm30_04.enums.EnumSOPClassUIDs;
import cdac.medinfo.sdk.dcm30_04.services.dicomnetcommons.EnumImplOpsStatus;
import cdac.medinfo.sdk.dcm30_04.services.dimsecommons.DicomMessage;
import cdac.medinfo.sdk.dcm30_04.services.print.dbhelper.Print_DBAgent;
import cdac.medinfo.sdk.dcm30_04.utils.DicomConfig;
import cdac.medinfo.sdk.dcm30_04.utils.DicomLogger;
import cdac.medinfo.sdk.dcm30_04.utils.ISingleCollection;
import cdac.medinfo.sdk.dcm30_04.utils.ResourceBundleWrapper;
import cdac.medinfo.sdk.dcm30_04.utils.StandardMethods;

/**
 * This class processes Dicom Request of Type N-Create, N-Set and N-Delete request for Basic Film Box SOP Class.
 */
class BasicFilmBoxDataSinkImpl 
{
	/**
	 * This function process N-Create, N-Set and N-Delete request for Basic Film Box SOP Class.
	 * Create of Basic Film Box internally creates instance of Image Box IOD also.
	 * It updates the mapping table with the values provided.
	 */
	@SuppressWarnings("unchecked")
	short store(Print_DBAgent objPrintDBAgent, DicomMessage objDicomMessage, String strValue) throws IOException, SQLException
	{
		EnumCommandField enumRequestType = objDicomMessage.getCommandType();
		switch(enumRequestType)
		{
		case N_CREATE_RQ :
		{
			String strBasicFilmBoxSOPInstance = objDicomMessage.getCommandSet().getValue(0x0000,0x1000).toString();
			String strImageBoxSOPInstanceUID = null;
			String strBasicAnnotationBoxSOPInstanceUID = null;
			String strPresentationLUTSOPInstanceUID = null;
			String strBasicFilmSessionSOPInstanceUID = null;
			IDataSet objIDataSet = objDicomMessage.getDataSet();
			ISingleCollection<IItem> objItemCollection = null;

			//First check whether film session for the corresponding SOP class is created or not
			if(objIDataSet.getValue(0x2010,0x0500) != null)
			{
				objItemCollection = (ISingleCollection<IItem>)objIDataSet.getValue(0x2010,0x0500);
				if(objItemCollection != null && objItemCollection.size() >0)
				{
					strBasicFilmSessionSOPInstanceUID =(String)objItemCollection.get(0).getValue(0x0008, 0x1155);
				}
				else if(strBasicFilmSessionSOPInstanceUID == null || objItemCollection.size() == 0)
				{
					if(DicomConfig.createInstance().isLoggingOn())
					{
						DicomLogger objDicomLogger =DicomLogger.getLogger();
						objDicomLogger.log(ResourceBundleWrapper.getValue("exceptions","InstanceCreationFailed", new Locale(DicomConfig.createInstance().getLocale())) + enumRequestType);
						objDicomLogger.log(ResourceBundleWrapper.getValue("exceptions","PrintManagement.BasicFilmSessionNotPresent", new Locale(DicomConfig.createInstance().getLocale())) + strBasicFilmSessionSOPInstanceUID);
					}
					return EnumImplOpsStatus.FAILURE.getValue();
				}

				if(objPrintDBAgent.isSOPInstanceExist(EnumSOPClassUIDs.BASICFILMSESSIONIOD, strBasicFilmSessionSOPInstanceUID))
				{
					if(objPrintDBAgent.createSOPInstance(EnumSOPClassUIDs.BASICFILMBOXIOD,objIDataSet,strBasicFilmBoxSOPInstance))
					{
						if(DicomConfig.createInstance().isLoggingOn())
						{
							DicomLogger objDicomLogger = DicomLogger.getLogger();
							objDicomLogger.log(ResourceBundleWrapper.getValue("status", "BasicFilmBoxSOPInstanceCreated", new Locale(DicomConfig.createInstance().getLocale())) + strBasicFilmBoxSOPInstance);
						}

						if(objIDataSet.getValue(0x2010,0x0520) != null)
						{
							objItemCollection = (ISingleCollection<IItem>)objIDataSet.getValue(0x2010,0x0520);
							if(objItemCollection != null && objItemCollection.size() !=0)
							{
								for(IItem itemBasicAnootation : objItemCollection)
								{
									String strSOPClassUID = (String)itemBasicAnootation.getValue(0x0008, 0x1150);
									strBasicAnnotationBoxSOPInstanceUID = (String)itemBasicAnootation.getValue(0x0008, 0x1155);
									IDataSet objBasicAnnotationBoxDataSet = getBasicAnnotationBoxDataSet(strSOPClassUID,strBasicAnnotationBoxSOPInstanceUID,objIDataSet);
									if(!objPrintDBAgent.createSOPInstance(EnumSOPClassUIDs.BASICANNOTATIONBOX, objBasicAnnotationBoxDataSet, strBasicAnnotationBoxSOPInstanceUID))
									{
										if(DicomConfig.createInstance().isLoggingOn())
										{
											DicomLogger objDicomLogger =DicomLogger.getLogger();
											objDicomLogger.log(ResourceBundleWrapper.getValue("exceptions","InstanceCreationFailed", new Locale(DicomConfig.createInstance().getLocale())) + enumRequestType);
										}
										return EnumImplOpsStatus.FAILURE.getValue();
									}
									else
									{
										if(DicomConfig.createInstance().isLoggingOn())
										{
											DicomLogger objDicomLogger = DicomLogger.getLogger();
											objDicomLogger.log(ResourceBundleWrapper.getValue("status", "BasicAnnotationBoxCreated", new Locale(DicomConfig.createInstance().getLocale())) + strBasicAnnotationBoxSOPInstanceUID);
										}
									}
								}
							}
						}
						objItemCollection = (ISingleCollection<IItem>)objIDataSet.getValue(0x2010,0x0510);
						for( IItem itemImageBox : objItemCollection)
						{
							String strSOPClassUID = (String)itemImageBox.getValue(0x0008, 0x1150);
							strImageBoxSOPInstanceUID = (String)itemImageBox.getValue(0x0008, 0x1155);
							IDataSet objImageBoxDataSet = getImageBoxDataSet(strSOPClassUID,strImageBoxSOPInstanceUID,objIDataSet);
							if(!objPrintDBAgent.createSOPInstance(EnumSOPClassUIDs.BASICGRAYSCALEIMAGEBOX, objImageBoxDataSet, strImageBoxSOPInstanceUID))
							{
								if(DicomConfig.createInstance().isLoggingOn())
								{
									DicomLogger objDicomLogger =DicomLogger.getLogger();
									objDicomLogger.log(ResourceBundleWrapper.getValue("exceptions","InstanceCreationFailed", new Locale(DicomConfig.createInstance().getLocale())) + enumRequestType);
								}
								return EnumImplOpsStatus.FAILURE.getValue();
							}
							else
							{
								if(DicomConfig.createInstance().isLoggingOn())
								{
									DicomLogger objDicomLogger = DicomLogger.getLogger();
									objDicomLogger.log(ResourceBundleWrapper.getValue("status", "BasicGrayScaleImageBoxCreated", new Locale(DicomConfig.createInstance().getLocale())) + strImageBoxSOPInstanceUID);
								}
							}
							ISingleCollection<IItem> objItemCollectionAnnotation = (ISingleCollection<IItem>)objIDataSet.getValue(0x2010,0x0520);
							if(objItemCollectionAnnotation != null && objItemCollectionAnnotation.size() !=0)
							{
								for(IItem itemBasicAnootation : objItemCollectionAnnotation)
								{
									strBasicAnnotationBoxSOPInstanceUID = (String)itemBasicAnootation.getValue(0x0008, 0x1155);
									if(!objPrintDBAgent.insertIntoRelationShipTable(strBasicFilmSessionSOPInstanceUID, strBasicFilmBoxSOPInstance, strImageBoxSOPInstanceUID, strBasicAnnotationBoxSOPInstanceUID, strPresentationLUTSOPInstanceUID,null))
									{
										if(DicomConfig.createInstance().isLoggingOn())
										{
											DicomLogger objDicomLogger =DicomLogger.getLogger();
											objDicomLogger.log(ResourceBundleWrapper.getValue("exceptions","InstanceCreationFailed", new Locale(DicomConfig.createInstance().getLocale())) + enumRequestType);
										}
										return EnumImplOpsStatus.FAILURE.getValue();
									}
								}
							}
							else
							{
								if(!objPrintDBAgent.insertIntoRelationShipTable(strBasicFilmSessionSOPInstanceUID, strBasicFilmBoxSOPInstance, strImageBoxSOPInstanceUID, strBasicAnnotationBoxSOPInstanceUID, strPresentationLUTSOPInstanceUID,null))
								{
									if(DicomConfig.createInstance().isLoggingOn())
									{
										DicomLogger objDicomLogger =DicomLogger.getLogger();
										objDicomLogger.log(ResourceBundleWrapper.getValue("exceptions","InstanceCreationFailed", new Locale(DicomConfig.createInstance().getLocale())) + enumRequestType);
									}
									return EnumImplOpsStatus.FAILURE.getValue();
								}
							}
						}
						return EnumImplOpsStatus.SUCCESS.getValue();
					}
					else
					{
						if(DicomConfig.createInstance().isLoggingOn())
						{
							DicomLogger objDicomLogger =DicomLogger.getLogger();
							objDicomLogger.log(ResourceBundleWrapper.getValue("exceptions","InstanceCreationFailed", new Locale(DicomConfig.createInstance().getLocale())) + enumRequestType);
						}
						return EnumImplOpsStatus.FAILURE.getValue();
					}
				}
				else
				{
					if(DicomConfig.createInstance().isLoggingOn())
					{
						DicomLogger objDicomLogger =DicomLogger.getLogger();
						objDicomLogger.log(ResourceBundleWrapper.getValue("exceptions","InstanceCreationFailed", new Locale(DicomConfig.createInstance().getLocale())) + enumRequestType);
						objDicomLogger.log(ResourceBundleWrapper.getValue("exceptions","PrintManagement.BasicFilmSessionNotPresent", new Locale(DicomConfig.createInstance().getLocale())) + strBasicFilmSessionSOPInstanceUID);
					}
					return EnumImplOpsStatus.FAILURE.getValue();
				}
			}
			else
			{
				if(DicomConfig.createInstance().isLoggingOn())
				{
					DicomLogger objDicomLogger =DicomLogger.getLogger();
					objDicomLogger.log(ResourceBundleWrapper.getValue("exceptions","InstanceCreationFailed", new Locale(DicomConfig.createInstance().getLocale())) + enumRequestType);
					objDicomLogger.log(ResourceBundleWrapper.getValue("exceptions","PrintManagement.BasicFilmSessionNotPresent", new Locale(DicomConfig.createInstance().getLocale())) + strBasicFilmSessionSOPInstanceUID);
				}
				return EnumImplOpsStatus.FAILURE.getValue();
			}
		}
		case N_SET_RQ :
		{
			String strSOPInstance = objDicomMessage.getCommandSet().getValue(0x0000,0x1001).toString();
			IDataSet objIDataSet = objDicomMessage.getDataSet();
			if(!objPrintDBAgent.isSOPInstanceExist(EnumSOPClassUIDs.BASICFILMBOXIOD,strSOPInstance))
			{
				if(DicomConfig.createInstance().isLoggingOn())
				{
					DicomLogger objDicomLogger =DicomLogger.getLogger();
					objDicomLogger.log(ResourceBundleWrapper.getValue("exceptions","NoInstanceCreated", new Locale(DicomConfig.createInstance().getLocale())) + strSOPInstance);
				}
				return EnumImplOpsStatus.FAILURE.getValue();
			}
			else
			{
				if(objPrintDBAgent.updateSOPInstance(EnumSOPClassUIDs.BASICFILMBOXIOD,objDicomMessage.getDataSet(),strSOPInstance))
				{
					ISingleCollection<IItem>objItemCollection = (ISingleCollection<IItem>)objIDataSet.getValue(0x2010,0x0500);
					if(objItemCollection != null && objItemCollection.size() !=0)
					{
						IItem itemPresentationLUT = objItemCollection.get(0);
						String strPresentationLUTSOPInstanceUID = (String)itemPresentationLUT.getValue(0x0008, 0x1155);
						if(!objPrintDBAgent.updateRelationShipTable(EnumSOPClassUIDs.BASICFILMBOXIOD,EnumSOPClassUIDs.PRESENTATIONLUTIOD, strSOPInstance, strPresentationLUTSOPInstanceUID))
						{
							return EnumImplOpsStatus.FAILURE.getValue();
						}
					}
					if(DicomConfig.createInstance().isLoggingOn())
					{
						DicomLogger objDicomLogger = DicomLogger.getLogger();
						objDicomLogger.log(ResourceBundleWrapper.getValue("status", "Print.BasicFilmBoxInstanceUpdated", new Locale(DicomConfig.createInstance().getLocale())) + strSOPInstance);
					}
					return EnumImplOpsStatus.SUCCESS.getValue();
				}
				else
				{
					if(DicomConfig.createInstance().isLoggingOn())
					{
						DicomLogger objDicomLogger =DicomLogger.getLogger();
						objDicomLogger.log(ResourceBundleWrapper.getValue("exceptions","InstanceUpdationFailed", new Locale(DicomConfig.createInstance().getLocale())) + strSOPInstance);
					}
					return EnumImplOpsStatus.FAILURE.getValue();
				}
			}
		}
		case N_DELETE_RQ :
		{
			String strSOPInstance = objDicomMessage.getCommandSet().getValue(0x0000,0x1001).toString();
			if(!objPrintDBAgent.isSOPInstanceExist(EnumSOPClassUIDs.BASICFILMBOXIOD,strSOPInstance))
			{
				if(DicomConfig.createInstance().isLoggingOn())
				{
					DicomLogger objDicomLogger =DicomLogger.getLogger();
					objDicomLogger.log(ResourceBundleWrapper.getValue("exceptions","NoInstanceCreated", new Locale(DicomConfig.createInstance().getLocale())) + strSOPInstance);
				}
				return EnumImplOpsStatus.FAILURE.getValue();
			}
			else
			{
				if(objPrintDBAgent.deleteSOPInstance(EnumSOPClassUIDs.BASICFILMBOXIOD,strSOPInstance))
				{
					if(DicomConfig.createInstance().isLoggingOn())
					{
						DicomLogger objDicomLogger = DicomLogger.getLogger();
						objDicomLogger.log(ResourceBundleWrapper.getValue("status", "Print.BasicFilmBoxInstanceDeleted", new Locale(DicomConfig.createInstance().getLocale())) + strSOPInstance);
					}
					return EnumImplOpsStatus.SUCCESS.getValue();
				}
				else
				{
					if(DicomConfig.createInstance().isLoggingOn())
					{
						DicomLogger objDicomLogger =DicomLogger.getLogger();
						objDicomLogger.log(ResourceBundleWrapper.getValue("exceptions","InstanceDeletionFailed", new Locale(DicomConfig.createInstance().getLocale())) + strSOPInstance);
					}
					return EnumImplOpsStatus.FAILURE.getValue();
				}
			}
		}
		default : 
		{
			if(DicomConfig.createInstance().isLoggingOn())
			{
				DicomLogger objDicomLogger =DicomLogger.getLogger();
				objDicomLogger.log(ResourceBundleWrapper.getValue("exceptions","ServiceRequestNotSupported", new Locale(DicomConfig.createInstance().getLocale())) + enumRequestType);
			}
			return EnumImplOpsStatus.FAILURE.getValue();
		}
		}
	}

	/**
	 * This function gets the Basic Annotation Box Data Set.
	 */
	private IDataSet getBasicAnnotationBoxDataSet(String strSOPClassUID, String strSOPInstanceUID, IDataSet objIDataSet)
	{
		IDataSet objBasicAnnotationBoxDataSet = new DataSet();
		addDataElementToDataSet(0x2030,0x0010,objIDataSet,objBasicAnnotationBoxDataSet);
		addDataElementToDataSet(0x2030,0x0020,objIDataSet,objBasicAnnotationBoxDataSet);
		return objBasicAnnotationBoxDataSet;
	}

	/**
	 * This function gets the Image Box DataSet.
	 */
	private IDataSet getImageBoxDataSet(String strSOPClassUID, String strSOPInstanceUID, IDataSet objIDataSet)
	{
		IDataSet objImageBoxDataSet = new DataSet(objIDataSet.getTransferSyntax());
		addDataElementToDataSet(0x2020,0x0010,objIDataSet,objImageBoxDataSet);
		addDataElementToDataSet(0x2020,0x0020,objIDataSet,objImageBoxDataSet);
		addDataElementToDataSet(0x2020,0x0130,objIDataSet,objImageBoxDataSet);
		addDataElementToDataSet(0x2010,0x0060,objIDataSet,objImageBoxDataSet);
		addDataElementToDataSet(0x2010,0x0080,objIDataSet,objImageBoxDataSet);
		addDataElementToDataSet(0x2020,0x0030,objIDataSet,objImageBoxDataSet);
		addDataElementToDataSet(0x2020,0x0040,objIDataSet,objImageBoxDataSet);
		addDataElementToDataSet(0x2130,0x00C0,objIDataSet,objImageBoxDataSet);
		if(strSOPClassUID.equals(EnumSOPClassUIDs.BASICGRAYSCALEIMAGEBOX.getValue()))
		{
			addDataElementToDataSet(0x2020,0x0110,objIDataSet,objImageBoxDataSet);
			addDataElementToDataSet(0x2010,0x0120,objIDataSet,objImageBoxDataSet);
			addDataElementToDataSet(0x2010,0x0130,objIDataSet,objImageBoxDataSet);
			addDataElementToDataSet(0x2010,0x0150,objIDataSet,objImageBoxDataSet);
			addDataElementToDataSet(0x2050,0x0500,objIDataSet,objImageBoxDataSet);
		}
		else
		{
			addDataElementToDataSet(0x2020,0x0111,objIDataSet,objImageBoxDataSet);
		}
		return objImageBoxDataSet;
	}

	/**
	 * this function adds dataElement to DataSet.
	 */
	private void addDataElementToDataSet(int iGroupNo, int iElementNo, IDataSet objIDataSet, IDataSet objDataSetToBeCreated)
	{
		boolean isImplicitType = isImplicitType(objIDataSet.iterator().next());
		IDataElement objDataElement = objIDataSet.getDataForTag(iGroupNo, iElementNo);
		if(objDataElement == null)
		{
			String strVR = objIDataSet.getDictionaryReader().getVR(iGroupNo, iElementNo);
			int iVR = StandardMethods.getiVRtype(strVR);
			setValue(null,iGroupNo, iElementNo,iVR,objDataSetToBeCreated,isImplicitType);
		}
		else
		{
			int iVR = getIVRType(objDataElement, objIDataSet);
			setValue(objDataElement.getValue(), objDataElement.getTag().getGroupNumber(),objDataElement.getTag().getElementNumber(),iVR, objDataSetToBeCreated,isImplicitType);
		}
	}

	/**
	 * This function returns true of the DataElement is of Implicit DE.
	 */
	private boolean isImplicitType(IDataElement objIDataElement)
	{
		if(objIDataElement instanceof ExplicitDE )
			return false;
		else
			return true;
	}

	/**
	 * This function returns the int value of VR type of Data Element.
	 */
	private int getIVRType(IDataElement objDataElement, IDataSet objIDataSet)
	{
		int iVR = 0;
		if(objDataElement instanceof ExplicitDE)
		{
			iVR = ((ExplicitDE)objDataElement).getIVRType();
		}
		else
		{
			String strVR = objIDataSet.getDictionaryReader().getVR(objDataElement.getTag().getGroupNumber(), objDataElement.getTag().getElementNumber());
			iVR = StandardMethods.getiVRtype(strVR);
		}
		return iVR;
	}

	/**
	 * This function sets the value of DataElement.
	 */
	private void setValue(Object objValue,int iGroupNumber,int iElementNumber, int iVR, IDataSet objIDataSet, boolean isImplicit)
	{
		IDictionaryReader objIDictionaryReader = objIDataSet.getDictionaryReader();
		ITransferSyntax objITransferSyntax = objIDataSet.getTransferSyntax();

		if(isImplicit)
		{
			IDataElement objIDataElement = new ImplicitDE(iGroupNumber,iElementNumber,objValue,objITransferSyntax,objIDictionaryReader);
			objIDataSet.addDataElement(objIDataElement);
		}
		else
		{
			IDataElement objIDataElement = new ExplicitDE(iGroupNumber,iElementNumber,iVR,objValue,objITransferSyntax,objIDictionaryReader);
			objIDataSet.addDataElement(objIDataElement);
		}
	}
}
