/*******************************************************************************
 *  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.testcases.customizedscp;
import java.io.IOException;

import cdac.medinfo.sdk.dcm30_04.baselibs.DataSet;
import cdac.medinfo.sdk.dcm30_04.baselibs.PrinterConfigurationSequence;
import cdac.medinfo.sdk.dcm30_04.baselibs.PrinterConfigurationSequenceItem;
import cdac.medinfo.sdk.dcm30_04.baselibs.ProposedStudySequence;
import cdac.medinfo.sdk.dcm30_04.baselibs.ProposedStudySequenceItem;
import cdac.medinfo.sdk.dcm30_04.baselibs.SQ;
import cdac.medinfo.sdk.dcm30_04.baselibs.TransferSyntax;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDataElement;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDataSet;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IItem;
import cdac.medinfo.sdk.dcm30_04.commoninterface.ITransferSyntax;
import cdac.medinfo.sdk.dcm30_04.dicommodel.basicfilmsession.BasicFilmSessionIOD;
import cdac.medinfo.sdk.dcm30_04.dicommodel.modules.BasicFilmSessionPresentationModule;
import cdac.medinfo.sdk.dcm30_04.dicommodel.modules.BasicFilmSessionRelationshipModule;
import cdac.medinfo.sdk.dcm30_04.dicommodel.modules.PrinterConfigurationModule;
import cdac.medinfo.sdk.dcm30_04.dicommodel.modules.PrinterModule;
import cdac.medinfo.sdk.dcm30_04.dicommodel.modules.SOPCommonModule;
import cdac.medinfo.sdk.dcm30_04.dicommodel.print.PrinterConfigurationIOD;
import cdac.medinfo.sdk.dcm30_04.dicommodel.print.PrinterIOD;
import cdac.medinfo.sdk.dcm30_04.enums.EnumDecimateCropResult;
import cdac.medinfo.sdk.dcm30_04.enums.EnumFilmDestination;
import cdac.medinfo.sdk.dcm30_04.enums.EnumLoggingLevel;
import cdac.medinfo.sdk.dcm30_04.enums.EnumMagnificationType;
import cdac.medinfo.sdk.dcm30_04.enums.EnumMediumType;
import cdac.medinfo.sdk.dcm30_04.enums.EnumPatientsSex;
import cdac.medinfo.sdk.dcm30_04.enums.EnumPrintPriority;
import cdac.medinfo.sdk.dcm30_04.enums.EnumPrinterStatus;
import cdac.medinfo.sdk.dcm30_04.enums.EnumPrinterStatusInfo;
import cdac.medinfo.sdk.dcm30_04.enums.EnumRequestedResolutionID;
import cdac.medinfo.sdk.dcm30_04.enums.EnumSOPClassUIDs;
import cdac.medinfo.sdk.dcm30_04.services.dimsecommons.DicomMessage;
import cdac.medinfo.sdk.dcm30_04.services.dimsecommons.IDataSink;
import cdac.medinfo.sdk.dcm30_04.services.ncreate.commons.NCreateRQ;
import cdac.medinfo.sdk.dcm30_04.services.ncreate.commons.NCreateRSP;
import cdac.medinfo.sdk.dcm30_04.services.print.printsinkimpl.NCreateImagePrintMangMeta_QueryModel;
import cdac.medinfo.sdk.dcm30_04.services.print.printsinkimpl.NSetImagePrintMangMeta_QueryModel;
import cdac.medinfo.sdk.dcm30_04.services.print.printsinkimpl.PrintDataSinkImpl;
import cdac.medinfo.sdk.dcm30_04.services.print.printsourceimpl.NGetImagePrintMangMeta_QueryModel;
import cdac.medinfo.sdk.dcm30_04.services.print.printsourceimpl.PrintDataSourceImpl;
import cdac.medinfo.sdk.dcm30_04.services.print.printsourceimpl.PrinterConfiguration;
import cdac.medinfo.sdk.dcm30_04.services.print.scu.PrintSCU;
import cdac.medinfo.sdk.dcm30_04.utils.DicomConfig;
import cdac.medinfo.sdk.dcm30_04.utils.ICollectionIterator;
import cdac.medinfo.sdk.dcm30_04.utils.ISingleCollection;
import cdac.medinfo.sdk.dcm30_04.utils.SingleCollection;

public class PrintQueryModel 
{
	String strAffectedSOPINstanceUIDForBasicFilmSession = null;
	public static void main(String args[])
	{
		try
		{
			DicomConfig objDicomConfig = DicomConfig.createInstance();
			//enable logging,specify the path of the directory where log files are created.
			//User can specify any directory in place of 'c:\DCM_Logs'.
			//If no directory is defined by user to create logs then it is created in User Temp DIR.
			objDicomConfig.enableLogging(EnumLoggingLevel.INFO, "c:/DCM_Logs");


			/*
			 * Populating Database with data set on which find request will be processed.
			 */
			PrintQueryModel objTest = new PrintQueryModel();
			
			/*
			 * Create Sink and Source Impl with ConnectionString and driver String.
			 * PrintDataSourceImpl and PrintDataSinkImpl are default implementation of library which uses JavaDB. 
			 * Sink and Source Impl process the storage , updation, deletion and retrieval process for all Print supported services. 
			 * The user has to start javaDB server before connection creation if Client Server model in java DB is used.
			 * The SQL Script needed to create database is provided at %InstallDir%/SQLScripts/PrintServiceDB.sql
			 * User has to first create the Database then it should be set in the Print SCP.
			 * This DataSink and DataSource should be set on process handler class working as Print SCP.
			 * User can also provide its own implementation of IDataSink and IDataSource interface for MPPS.
			 */
			String dataBasePath = "D:/DataBase/PrintSDKdb";
			String ConnectionString = "jdbc:derby://localhost:5050/" + dataBasePath ;
			String driverString = "org.apache.derby.jdbc.ClientDriver";

			/*
			 * Add Print Handler to Print DataSource Impl to receive created data set 
			 * of Stored Print IOD and HardCopyGrayScale Image IOD
			 */
			IDataSink objPrintDataSink = new PrintDataSinkImpl(ConnectionString,driverString);
			PrintDataSourceImpl objPrintDataSourceImpl = new PrintDataSourceImpl(ConnectionString,driverString);
			PrintHandler objPrintHandler = new PrintHandler();
			objPrintDataSourceImpl.addPrinterHandler(objPrintHandler);
			
			// N-CREATE
			IDataSet objCreateDS = objTest.getBasicFilmSessionDataSetForCreate();
			
			NCreateImagePrintMangMeta_QueryModel objCreateQM = new NCreateImagePrintMangMeta_QueryModel(EnumSOPClassUIDs.BASICFILMSESSIONIOD);
			objCreateQM.decode(objCreateDS);
			
			short shResultCreate = objPrintDataSink.store(objCreateQM, "1.1.1.12.2.2.2.2.3");
			
			// display create DS of create
			NCreateImagePrintMangMeta_QueryModel objRsltQRYModel = (NCreateImagePrintMangMeta_QueryModel)objCreateQM;
			ISingleCollection<IDataSet> rstdatasetlist = new SingleCollection<IDataSet>();
			ITransferSyntax objITransferSyntax = new TransferSyntax();
			objRsltQRYModel.encode(objITransferSyntax, rstdatasetlist);
			
			IDataSet objRSLTDataCreate = rstdatasetlist.elementAt(0);
			objTest.display(objRSLTDataCreate);
			
			System.out.println("\n\n shResultCreate = " + shResultCreate);
			
			//---------------------
			
			// N-SET
			IDataSet objSetDS = objTest.getBasicFilmSessionDataSetForSet();
			
			NSetImagePrintMangMeta_QueryModel objSetQM = new NSetImagePrintMangMeta_QueryModel(EnumSOPClassUIDs.BASICFILMSESSIONIOD);
			objSetQM.decode(objSetDS);
			
			short shResultSet = objPrintDataSink.store(objSetQM, "1.1.1.12.2.2.2.2.3");
			
			// display Set DS 
			NSetImagePrintMangMeta_QueryModel objRsltQRYModel2 = (NSetImagePrintMangMeta_QueryModel)objSetQM;
			ISingleCollection<IDataSet> rstdatasetlist2 = new SingleCollection<IDataSet>();
			ITransferSyntax objITransferSyntax2 = new TransferSyntax();
			objRsltQRYModel2.encode(objITransferSyntax2, rstdatasetlist2);
			
			IDataSet objRSLTDataSet2 = rstdatasetlist2.elementAt(0);
			objTest.display(objRSLTDataSet2);
			
			System.out.println("\n\n shResultSet = " + shResultSet);
			
			//--------------------------------
			
			// N-Get
			
			PrinterConfiguration objPrinterConfiguration = new PrinterConfiguration();
			PrinterIOD objPrinterIOD = new PrinterIOD();
			objTest.populatePrinterIOD(objPrinterIOD);
			objPrinterConfiguration.setPrintIOD(objPrinterIOD);
			
			objPrintDataSourceImpl.setPrinterConfigurationInfo(objPrinterConfiguration);
			
	//		IDataSet objGetDS = objTest.populatePrinterConfigurationIOD(); //added 
			
			NGetImagePrintMangMeta_QueryModel objGetQM = new NGetImagePrintMangMeta_QueryModel(EnumSOPClassUIDs.PRINTERIOD, "1.2.840.10008.5.1.1.16");
	//		objGetQM.decode(objGetDS); //added
			
			NGetImagePrintMangMeta_QueryModel objRstQueryModel = new NGetImagePrintMangMeta_QueryModel(EnumSOPClassUIDs.PRINTERIOD, "1.2.840.10008.5.1.1.16");
			
			short shResultGet = objPrintDataSourceImpl.retrieve(objGetQM, objRstQueryModel);
			
			ISingleCollection<IDataSet> rstdatasetlistGet = new SingleCollection<IDataSet>();
			ITransferSyntax objITransferSyntaxGet = new TransferSyntax();
			objRstQueryModel.encode(objITransferSyntaxGet, rstdatasetlistGet);
			
			IDataSet objRSLTDataSetGet = rstdatasetlistGet.elementAt(0);
			
			objTest.display(objRSLTDataSetGet);
			
			System.out.println("\n\n shResultGet = " + shResultGet);
			
			
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}
	
	/*
	 * Displays the DataElements of Dataset
	 */
	private void display(IDataSet objIDataSet)
	{
		ICollectionIterator<IDataElement> objIDataSetIterator = objIDataSet.iterator();

		System.out.println("Tag     Value");
		while(objIDataSetIterator.hasNext())
		{
			IDataElement objDataElement = objIDataSetIterator.next();				

			if(!(objDataElement.getDicomValue() instanceof SQ))
			{

				System.out.println(objDataElement.getTag().getGroupNumber()+"    "+
						objDataElement.getTag().getElementNumber()+"    "+
						objDataElement.getDicomValue().toString());
			}
			else  
			{
				displaySequence((SQ)objDataElement.getDicomValue(),"> ");					
			}
		}

	}

	/*
	 * This method diaplays the SQ data type.
	 */
	private void displaySequence(SQ objSQDataElement,String ss)
	{
		ICollectionIterator<IItem> objSQItemIterator = objSQDataElement.iterator();
		int i = 1;
		while(objSQItemIterator.hasNext())
		{
			System.out.println("ITEM :"+ i++ );
			IItem objItem = objSQItemIterator.next();
			ICollectionIterator<IDataElement> objDataElementIterator = objItem.iterator();
			while(objDataElementIterator.hasNext())
			{
				IDataElement objDataElement = objDataElementIterator.next();

				if(!(objDataElement.getDicomValue() instanceof SQ))
				{
					System.out.println(ss +objDataElement.getTag().getGroupNumber()+"    "+
							objDataElement.getTag().getElementNumber()+"    "+
							objDataElement.getDicomValue().toString());						 

				}
				else
				{
					displaySequence((SQ)objDataElement.getDicomValue(),ss+ss);
				}	 
			}
		}
	}
	
	/*
	 * *************************************************************************
	 * This block of code creates the PrintSCU to perform the process of 
	 * SOP Instance creation operation for Basic Film Session.
	 * It initializes the NCreate RQ and sends it to SCP using PrintSCU.
	 * *************************************************************************
	 */
	public void doNCreateForBasicFilmSession(PrintSCU objPrintSCU) throws IOException
	{

		//Genarating Dataset for Basic Film Session N-Create.
		IDataSet objIDataSet = 	getBasicFilmSessionDataSetForCreate();

		System.out.println("N-Create Request For basic Film Session is Initialized................");

		//Initializing NCreate RQ 
		NCreateRQ objNCreateRQ = NCreateRQ.getDefaultRQ(EnumSOPClassUIDs.BASICFILMSESSIONIOD.getValue(), null, objIDataSet);
		NCreateRSP objNCreateRSP = null;

		//sending RQ to SCP
		if(objPrintSCU.sendMessage(objNCreateRQ))
		{
			System.out.println("Response of N-Create For Basic Print Session  is received");

			/*
			 * Get the Response collection from the Print SCU.
			 */
			ISingleCollection<DicomMessage> objSingleCollection = objPrintSCU.getDIMSEResponse();
			System.out.println("Response Size collection :: " + objSingleCollection.size());

			//Get the Dicom Message from the Collection
			DicomMessage objDicomMessage = objSingleCollection.get(objSingleCollection.size()-1);

			//Printing Status of N-Create for Basic Film Session
			objNCreateRSP = new NCreateRSP(objDicomMessage);
			strAffectedSOPINstanceUIDForBasicFilmSession = objNCreateRSP.getAffectedSOPInstanceUID();
			System.out.println("Status For N-Create For Basic Print Session " + objNCreateRSP.getStatus());

			//If the DataSet is present in the response print the DataSet.
			IDataSet objIDataSet2 = objDicomMessage.getDataSet();
			if(objIDataSet2 != null)
			{
				System.out.println("*********************************************");
				display(objIDataSet2);
				System.out.println("*********************************************");
			}

		}
		else
			System.out.println("N-Create For Basic Print Session  operation failed.");
	}
	
	/*
	 * Get the BasicFilmSessionDataSetForCreate
	 */
	IDataSet getBasicFilmSessionDataSetForCreate()
	{
		ITransferSyntax objITransferSyntax = new TransferSyntax("1.2.840.10008.1.2.4.50");
		IDataSet objIDataSet = new DataSet(objITransferSyntax);//new DataSet();
		BasicFilmSessionIOD objBasicFilmSessionIOD = new BasicFilmSessionIOD(objIDataSet);
		BasicFilmSessionPresentationModule objBasicFilmSessionPresentationModule = objBasicFilmSessionIOD.getBasicFilmSessionPresentationModule();
		objBasicFilmSessionPresentationModule.setNumberOfCopies("1");
		objBasicFilmSessionPresentationModule.setPrintPriority(EnumPrintPriority.HIGH);
		objBasicFilmSessionPresentationModule.setMediumType(EnumMediumType.BLUE_FILM);
		objBasicFilmSessionPresentationModule.setFilmDestination(EnumFilmDestination.PROCESSOR);
		objBasicFilmSessionPresentationModule.setOwnerID("1");

		BasicFilmSessionRelationshipModule objBasicFilmSessionRelationshipModule = objBasicFilmSessionIOD.getBasicFilmSessionRelationshipModule();
		ProposedStudySequence objProposedStudySequence = objBasicFilmSessionRelationshipModule.getProposedStudySequence();
		ProposedStudySequenceItem objProposedStudySequenceItem = objProposedStudySequence.getNewItem();
		objProposedStudySequenceItem.setAccessionNumber("1");
		objProposedStudySequenceItem.setAdditionalPatientHistory("No Addition History Of the Patient is Present");
		objProposedStudySequenceItem.setStudyTime("101010");
		objProposedStudySequenceItem.setStudyInstanceUID("1.3.12.2.1107.5.4.3.49");
		objProposedStudySequenceItem.setStudyID("1");
		objProposedStudySequenceItem.setStudyDate("20091010");
		objProposedStudySequenceItem.setStudyDescription("Study Description");
		objProposedStudySequenceItem.setStudyDate("20091010");
		objProposedStudySequenceItem.setSeriesNumber("11");
		objProposedStudySequenceItem.setReferringPhysicianName("Refering Physician Name");
		objProposedStudySequenceItem.setPatientWeight("21");
		objProposedStudySequenceItem.setPatientSex(EnumPatientsSex.FEMALE);
		objProposedStudySequenceItem.setPatientName("Patient Name");
		objProposedStudySequenceItem.setPatientID("1");
		objProposedStudySequenceItem.setPatientComments("Patient Comments ");
		objProposedStudySequenceItem.setPatientBirthTime("121212");
		objProposedStudySequenceItem.setPatientBirthDate("20091010");
		objProposedStudySequenceItem.setPatientAge("098Y");
		objProposedStudySequenceItem.setOccupation("Occupation");
		objProposedStudySequence.addItem(objProposedStudySequenceItem);
		return objIDataSet;
	}
	
	/*
	 * Get the BasicFilmSessionDataSetForSet
	 */
	IDataSet getBasicFilmSessionDataSetForSet()
	{
		IDataSet objIDataSet = new DataSet();
		BasicFilmSessionIOD objBasicFilmSessionIOD = new BasicFilmSessionIOD(objIDataSet);
		BasicFilmSessionPresentationModule objBasicFilmSessionPresentationModule = objBasicFilmSessionIOD.getBasicFilmSessionPresentationModule();
		objBasicFilmSessionPresentationModule.setNumberOfCopies("1");
		objBasicFilmSessionPresentationModule.setPrintPriority(EnumPrintPriority.HIGH);
		objBasicFilmSessionPresentationModule.setMediumType(EnumMediumType.BLUE_FILM);
		objBasicFilmSessionPresentationModule.setFilmDestination(EnumFilmDestination.PROCESSOR);

		BasicFilmSessionRelationshipModule objBasicFilmSessionRelationshipModule = objBasicFilmSessionIOD.getBasicFilmSessionRelationshipModule();
		ProposedStudySequence objProposedStudySequence = objBasicFilmSessionRelationshipModule.getProposedStudySequence();
		ProposedStudySequenceItem objProposedStudySequenceItem = objProposedStudySequence.getNewItem();
		objProposedStudySequenceItem.setAccessionNumber("2");
		objProposedStudySequenceItem.setAdditionalPatientHistory("No Addition History Of the Patient is Present");
		objProposedStudySequenceItem.setStudyTime("123121");
		objProposedStudySequenceItem.setStudyInstanceUID("1.3.12.2.1107.5.4.3.49");
		objProposedStudySequenceItem.setStudyID("1");
		objProposedStudySequenceItem.setStudyDate("20091010");
		objProposedStudySequenceItem.setStudyDescription("Modified Study Description");
		objProposedStudySequenceItem.setStudyDate("20091010");
		objProposedStudySequenceItem.setSeriesNumber("1");
		objProposedStudySequenceItem.setReferringPhysicianName("Modified Refering Physician Name");
		objProposedStudySequenceItem.setPatientWeight("33");
		objProposedStudySequenceItem.setPatientSex(EnumPatientsSex.FEMALE);
		objProposedStudySequenceItem.setPatientName("Modified Patient Name");
		objProposedStudySequenceItem.setPatientID("33");
		objProposedStudySequenceItem.setPatientComments("Modified Patient Comments ");
		objProposedStudySequenceItem.setPatientBirthTime("121212");
		objProposedStudySequenceItem.setPatientBirthDate("20091010");
		objProposedStudySequenceItem.setPatientAge("017M");
		objProposedStudySequenceItem.setOccupation("JOBLESS");
		objProposedStudySequence.addItem(objProposedStudySequenceItem);
		return objIDataSet;
	}
	
	/*
	 * This function populates the Printer Configuration IOD.
	 */
	 void populatePrinterConfigurationIOD(PrinterConfigurationIOD objPrinterConfigurationIOD)
	{
		PrinterConfigurationModule objPrinterConfigurationModule = objPrinterConfigurationIOD.getPrinterConfigurationModule();

		PrinterConfigurationSequence objPrinterConfigurationSequence = objPrinterConfigurationModule.getPrinterConfigurationSequence();
		PrinterConfigurationSequenceItem objPrinterConfigurationSequenceItem = objPrinterConfigurationSequence.getNewItem();
		objPrinterConfigurationSequenceItem.setConfigurationInformationDescription("IMPLEMENTATION_SPECIFIC_CURVE_TYPE");
		objPrinterConfigurationSequenceItem.setDecimateCropResult(EnumDecimateCropResult.PRINTER_DOES_NOT_SUPPORTS_DECIMATE_CROP_RESULT_CROP);
		objPrinterConfigurationSequenceItem.setDefaultMagnificationType(EnumMagnificationType.BILINEAR);
		objPrinterConfigurationSequenceItem.setDefaultPrinterResolutionID(EnumRequestedResolutionID.HIGH);
		objPrinterConfigurationSequenceItem.setDefaultSmoothingType("SMOOTH");
		objPrinterConfigurationSequenceItem.setMaximumCollatedFilms("2");
		objPrinterConfigurationSequenceItem.setMaximumMemoryAllocation("8");
		objPrinterConfigurationSequenceItem.setMemoryBitDepth((short)0);
		objPrinterConfigurationSequenceItem.setPrintingBitDepth((short)0);
		objPrinterConfigurationSequence.addItem(objPrinterConfigurationSequenceItem);
	}
	 
		/*
		 * This function populates the Printer IOD.
		 */
		private void populatePrinterIOD(PrinterIOD objPrinterIOD)
		{
			PrinterModule objPrinterModule = objPrinterIOD.getPrinterModule();
			String[] strArrValue = new String[2];
			strArrValue[0] = "19941010";
			strArrValue[1] = "19991010";
			objPrinterModule.setDateOfLastCalibration(strArrValue);
			objPrinterModule.setDeviceSerialNumber("4");
			objPrinterModule.setManufacturer("Manufacture");
			objPrinterModule.setManufacturerModelName("Manufacturer Model Name");
			objPrinterModule.setPrinterName("SDK DICOM Printer");
			objPrinterModule.setPrinterStatus(EnumPrinterStatus.NORMAL);
			objPrinterModule.setPrinterStatusInfo(EnumPrinterStatusInfo.NORMAL);
			String[] strArrValue1 = new String[2];
			strArrValue1[0] = "1";
			strArrValue1[1] = "1";
			objPrinterModule.setSoftwareVersions(strArrValue1);
			String[] strArrValue2 = new String[2];
			strArrValue2[0] = "0710";
			strArrValue2[1] = "0710";
			objPrinterModule.setTimeOfLastCalibration(strArrValue2);

			SOPCommonModule objSOPCommonModule = objPrinterIOD.getSOPCommonModule();
			objSOPCommonModule.setSOPClassUID(EnumSOPClassUIDs.PRINTERIOD.getValue());
			objSOPCommonModule.setSOPInstanceUID("1.2.840.10008.5.1.1.17");
		}
}
