package cdac.medinfo.sdk.dcm30_04.services.wadors;

import cdac.medinfo.sdk.dcm30_04.baselibs.DataSet;
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.enums.EnumPDUType;
import cdac.medinfo.sdk.dcm30_04.enums.EnumSOPClassUIDs;
import cdac.medinfo.sdk.dcm30_04.services.association.AAbort;
import cdac.medinfo.sdk.dcm30_04.services.association.AReleaseRQorRP;
import cdac.medinfo.sdk.dcm30_04.services.association.AssociateRQ;
import cdac.medinfo.sdk.dcm30_04.services.association.DefaultAssociation;
import cdac.medinfo.sdk.dcm30_04.services.association.RQPresContext;
import cdac.medinfo.sdk.dcm30_04.services.cget.commons.CGetRQ;
import cdac.medinfo.sdk.dcm30_04.services.cget.commons.CGetRSP;
import cdac.medinfo.sdk.dcm30_04.services.cget.scu.CGetSCU;
import cdac.medinfo.sdk.dcm30_04.services.dimsecommons.DicomMessage;
import cdac.medinfo.sdk.dcm30_04.services.scu.commons.SCUSession;
import cdac.medinfo.sdk.dcm30_04.utils.DicomConstants;
import cdac.medinfo.sdk.dcm30_04.utils.ISingleCollection;
import cdac.medinfo.sdk.dcm30_04.utils.SingleCollection;
/**
 * This class helps to retrieves the frame data.
 * i.e. frames requested in the URL request.
 * It send request to the FLR service. 
 */
public class RetriveFrameData {
/**
 * This method retrieve the Frame level data from the service.
 * @param studyInstanceUID
 * @param seriesInstanceUID
 * @param sopInstanceUID
 * @param frameList
 * @return destination path of the retrieve file.
 */
public String retriveFrameService(String studyInstanceUID, String seriesInstanceUID, String sopInstanceUID, int[] frameList)
{

	//SCU Session.
	SCUSession objSession = null;

	try
	{
		//Create SCUSession object
		objSession = new SCUSession();
		String filePath = null;
		/*
		 * Initializes the service types and populates the default association
		 */
		ISingleCollection<RQPresContext> objPressConColl = new SingleCollection<RQPresContext>();

		//RQ Pres Context for X-Ray
		RQPresContext objRQPresContextXRay = new RQPresContext();
		objRQPresContextXRay.setAbstractSyntaxName(EnumSOPClassUIDs.XRAYANGIOGRAPHICIOD.getValue());
		objRQPresContextXRay.addTransferSyntax(DicomConstants.TS_LOSSY_JPEG_8_BIT);
		
		//RQ Pres Context for enhanced MR
		RQPresContext objRQPresContextMR = new RQPresContext();
		objRQPresContextMR.setAbstractSyntaxName(EnumSOPClassUIDs.MRIOD.getValue());
		objRQPresContextMR.addTransferSyntax(DicomConstants.TS_EXPLICIT_VR_LITTLE_ENDIAN);
		
		//RQ Pres Context for enhanced MR
		RQPresContext objRQPresContextEnhancedMR = new RQPresContext();
		objRQPresContextEnhancedMR.setAbstractSyntaxName(EnumSOPClassUIDs.ENHANCEDMRIOD.getValue());
		objRQPresContextEnhancedMR.addTransferSyntax(DicomConstants.TS_EXPLICIT_VR_LITTLE_ENDIAN);
		

		//RQ Pres Context for Composite Instance Root Retrieve - GET
		RQPresContext objRQPresContextComposedInstance = new RQPresContext();
		objRQPresContextComposedInstance.setAbstractSyntaxName(EnumSOPClassUIDs.DCM_COMPOSITE_INSTANCE_ROOT_RETRIEVE_GET.getValue());
		objRQPresContextComposedInstance.addTransferSyntax(DicomConstants.TS_DEFAULT_IMPLICIT_VR_LITTLE_ENDIAN);
		
		
		//RQ Pres Context for enhanced US Muli-frame
		RQPresContext objRQPresContextUSMULTIFRAME = new RQPresContext();
		objRQPresContextUSMULTIFRAME.setAbstractSyntaxName(EnumSOPClassUIDs.USMULTIFRAME.getValue());
		objRQPresContextUSMULTIFRAME.addTransferSyntax(DicomConstants.TS_DEFAULT_IMPLICIT_VR_LITTLE_ENDIAN);

		objPressConColl.add(objRQPresContextUSMULTIFRAME);
		objPressConColl.add(objRQPresContextMR);
		objPressConColl.add(objRQPresContextXRay);
		objPressConColl.add(objRQPresContextEnhancedMR);
		objPressConColl.add(objRQPresContextComposedInstance);

		DefaultAssociation objDefaultAssociation = new DefaultAssociation("SDK");
		objDefaultAssociation.loadAssociation(objPressConColl);

		//Create Association RQ
		AssociateRQ objAssociateRQ = objDefaultAssociation.getAssociationRQ("SDK");

		//Start SCU Session by providing the IP address and Port of SCP.
		objSession.start("localhost", 9003);

		//Create CGet SCU object using the current SCU Session.
		CGetSCU objCGetSCU = new CGetSCU(objSession);

		//The destination path where the retrieved dataset should be stored.
		objCGetSCU.setDestinationPath(RetriveDataServer.path);

		//Send the Association Request
		if(objSession.sendAssociationMessage(objAssociateRQ))
		{
			System.out.println("Assocaition is established");
			/*
			 * Creating DataSet for C-Get Request.
			 */
			IDataSet objIDataSet = new DataSet();
			IDictionaryReader objIDictionaryReader = objIDataSet.getDictionaryReader();
			
			//passing SOPInstanceUID (0008,0018)
			IDataElement objIDataElement = new ImplicitDE(0x0008,0x0018,sopInstanceUID,objIDictionaryReader);
			objIDataSet.addDataElement(objIDataElement);
			
			//passing Retrieve Level (0000,0052) either Image or Frame
			objIDataElement = new ImplicitDE(0x0008,0x0052,"Frame",objIDictionaryReader);
			objIDataSet.addDataElement(objIDataElement);
			
			int CalculatedFrameList[]=frameList;
			objIDataElement = new ImplicitDE(0x0008,0x1162,CalculatedFrameList,objIDictionaryReader);
			objIDataSet.addDataElement(objIDataElement);
			
			//passing Time Range (0008,1163)
			//double time[]={0.2,0.3};
			//objIDataElement = new ImplicitDE(0x0008,0x1163,time,objIDictionaryReader);
			//objIDataSet.addDataElement(objIDataElement);


			objIDataElement = new ImplicitDE(0x0000,0x0002,DicomConstants.DCM_COMPOSITE_INSTANCE_ROOT_RETRIEVE_GET,objIDictionaryReader);
			objIDataSet.addDataElement(objIDataElement);
			
			//Create Default CGetRQ by giving the DataSet. This method uses
			// default values for the attributes in the request. These attributes can be
			//modified once the request object is created, before sending.
			CGetRQ objCGetRQ = CGetRQ.getDefaultRQ(DicomConstants.DCM_COMPOSITE_INSTANCE_ROOT_RETRIEVE_GET, objIDataSet);

			//Send the C-Get-RQ and wait for a C-Get-RSP.This method exits once the response is received. This response is 
			//added in the response collection maintained by the CGetSCU which can be retrieved. This method return true if request is successfully sent 
			//to the SCP and false if the message cannot be sent to the SCP( for e.g. if the association status is false or if SOP class UID is not agreed in agreed association.
			
			if(objCGetSCU.sendMessage(objCGetRQ))
			{
				System.out.println("CGet operation performed");
				ISingleCollection<DicomMessage> objSingleCollection = objCGetSCU.getDIMSEResponse();
				System.out.println("Size of Response collection :: " + objSingleCollection.size());
				/*
				 * This will get the pending response from the Dicom Message and displays it.
				 */
				for(DicomMessage objDicomMessage : objSingleCollection)
				{
					CGetRSP objCGetRSP = new CGetRSP(objDicomMessage);
					System.out.println("Response Status  :" + Integer.toHexString(objCGetRSP.getStatus()));
					 filePath = objCGetSCU.getDestinationPath();
				}
				System.out.println("CGet_SCU file destination path  =  "+objCGetSCU.getDestinationPath());
			}
			else
				System.out.println("CGet operation Failed");


			//Create A-Release-RQ to release the association
			AReleaseRQorRP objAReleaseRQorRP = new AReleaseRQorRP(EnumPDUType.RELEASE_RQ);

			//Send the A-Release-RQ
			if(objSession.sendAssociationMessage(objAReleaseRQorRP))
			{
				System.out.println("Release Response received");

				//When successful A-Release-RP is received, close the Session.
				//Please note that instead of closing the session we can create 
				//another association and send more requests. Also it is possible
				//to create multiple C-Get-RQs and send them one by one.
				objSession.close();
			}

			//In case an ABORT is received from SCP during the C-Get operation
			if(objSession.getDIMSEAssociation() instanceof AAbort)
			{
				System.out.println("Abort arrives. Closing session.");
				objSession.close();
			}
			return filePath;
		}
		else
		{
			System.out.println("Association cannot be established");
			objSession.close();
		}
	}
	catch(Exception e)
	{
		e.printStackTrace();
		objSession.close();
	}

	return null;
	
}
	
}
