/*******************************************************************************
 *  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.tlsscp.commons;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Locale;


import cdac.medinfo.sdk.dcm30_04.services.association.AssociationLoadFailedException;
import cdac.medinfo.sdk.dcm30_04.services.association.DefaultAssociation;
import cdac.medinfo.sdk.dcm30_04.services.dimsecommons.EnumSCPSessionStopListeningOptions;
import cdac.medinfo.sdk.dcm30_04.services.scp.commons.SCPController;
import cdac.medinfo.sdk.dcm30_04.services.scp.commons.SCPSession;
import cdac.medinfo.sdk.dcm30_04.services.tls.commons.TLSServerConfig;
import cdac.medinfo.sdk.dcm30_04.utils.DicomConfig;
import cdac.medinfo.sdk.dcm30_04.utils.DicomLogger;
import cdac.medinfo.sdk.dcm30_04.utils.EnumFeatureList;
import cdac.medinfo.sdk.dcm30_04.utils.ResourceBundleWrapper;


/**
 *  This class starts the TLS SCP Session. TLSSCPSession is responsible for accepting TLS connections from SCUs.
 *  TLSSCPSession can be configured to accept both secured and unsecured connections.
 *  It also maintains the Default capability of supported Presentation Contexts in the form of  {@link DefaultAssociation}
 *  Before the SCPSession is started to listen for accepting connections, it is necessary to configure the SCPSession.
 *  This configuration involves adding the {@link ProcessHandler},{@link DefaultAssociation} onto the SCPSession.
 */
public class TLSSCPSession extends SCPSession 
{

	
	

	
	/**
	 * This method starts the SCP session for both secured and unsecured communication on specified IP and ports.
	 * @param strAETitle Application Entity Title representation used to identify the DICOM nodes communicating between each other.
	 * @param strIP String value of IP.
	 * @param iunsecurePort int value of port for unsecured communication.
	 * @param isecurePort int value of port for secured communication.
	 * @param objTLSServerConfig SCP configuration for secure communication.
	 * @throws IOException Signals that an I/O exception has occurred.
	 */
	public void start(String strAETitle,String strIP, int iunsecurePort,int isecurePort,TLSServerConfig objTLSServerConfig) throws IOException,AssociationLoadFailedException
	{
		
		controller = new TLSSCPController();
		initDefaultAssociation(strAETitle);
		controller.setProcessHandler(objIProcessHandler);
		((TLSSCPController)controller).accept(new InetSocketAddress(strIP,iunsecurePort),new InetSocketAddress(strIP,isecurePort),objTLSServerConfig,itimeout);
	}

	
	/**
	 * This method starts the SCP session for secured communication on specified IP and ports.
	 * @param strAETitle Application Entity Title representation used to identify the DICOM nodes communicating between each other.
	 * @param strIP String value of IP.
	 * @param isecurePort int value of port for secured communication.
	 * @param objTLSServerConfig SCP configuration for secure communication.
	 * @throws IOException Signals that an I/O exception has occurred.
	 */
	public void start(String strAETitle,String strIP,int isecurePort,TLSServerConfig objTLSServerConfig) throws IOException,AssociationLoadFailedException
	{
		
		controller = new TLSSCPController();
		initDefaultAssociation(strAETitle);
		controller.setProcessHandler(objIProcessHandler);
		((TLSSCPController)controller).accept(null,new InetSocketAddress(strIP,isecurePort),objTLSServerConfig,itimeout);
	}
	
	

	/**
	 * This method starts the SCP session for both secured and unsecured communication on specified IP and ports.
	 * @param strAETitle Application Entity Title representation used to identify the DICOM nodes communicating between each other.
	 * @param iunsecurePort int value of port for unsecured communication.
	 * @param isecurePort int value of port for secured communication.
	 * @param objTLSServerConfig SCP configuration for secure communication.
	 * @throws IOException Signals that an I/O exception has occurred.
	 */
	public void start(String strAETitle,int iunsecurePort,int isecurePort,TLSServerConfig objTLSServerConfig)throws IOException
	{
		controller = new TLSSCPController();
		initDefaultAssociation(strAETitle);
		controller.setProcessHandler(objIProcessHandler);
		((TLSSCPController)controller).accept(new InetSocketAddress(InetAddress.getLocalHost(),iunsecurePort)
		,new InetSocketAddress(InetAddress.getLocalHost(),isecurePort)
		,objTLSServerConfig,itimeout);
	}


	/**
	 * This method starts the SCP session for secured communication on specified IP and ports.
	 * @param strAETitle Application Entity Title representation used to identify the DICOM nodes communicating between each other.
	 * @param isecurePort int value of port for secured communication.
	 * @param objTLSServerConfig SCP configuration for secure communication.
	 * @throws IOException Signals that an I/O exception has occurred.
	 */
	public void start(String strAETitle,int isecurePort,TLSServerConfig objTLSServerConfig)throws IOException
	{
		controller = new TLSSCPController();
		initDefaultAssociation(strAETitle);
		controller.setProcessHandler(objIProcessHandler);
		((TLSSCPController)controller).accept(null
		,new InetSocketAddress(InetAddress.getLocalHost(),isecurePort)
		,objTLSServerConfig,itimeout);
	}
	
	
	/**
	 * This method starts the SCP session for both secured and unsecured communication on specified IP and ports.
	 * @param strAETitle Application Entity Title representation used to identify the DICOM nodes communicating between each other.
	 * @param ip instance of INet Address.
	 * @param iunsecurePort int value of port for unsecured communication.
	 * @param isecurePort int value of port for secured communication.
	 * @param objTLSServerConfig SCP configuration for secure communication.
	 * @throws IOException  Signals that an I/O exception has occurred.
	 */
	public void start(String strAETitle,InetAddress ip,int iunsecurePort,int isecurePort,TLSServerConfig objTLSServerConfig)throws IOException
	{

		controller = new TLSSCPController();
		initDefaultAssociation(strAETitle);
		controller.setProcessHandler(objIProcessHandler);
		((TLSSCPController)controller).accept(new InetSocketAddress(ip,iunsecurePort)
		,new InetSocketAddress(ip,isecurePort),objTLSServerConfig,itimeout);
	}	

	
	/**
	 * This method starts the SCP session for secured communication on specified IP and ports.
	 * @param strAETitle Application Entity Title representation used to identify the DICOM nodes communicating between each other.
	 * @param ip instance of INet Address.
	 * @param isecurePort int value of port for secured communication.
	 * @param objTLSServerConfig SCP configuration for secure communication.
	 * @throws IOException  Signals that an I/O exception has occurred.
	 */
	public void start(String strAETitle,InetAddress ip,int isecurePort,TLSServerConfig objTLSServerConfig)throws IOException
	{
		controller = new TLSSCPController();
		initDefaultAssociation(strAETitle);
		controller.setProcessHandler(objIProcessHandler);
		((TLSSCPController)controller).accept(null
		,new InetSocketAddress(ip,isecurePort),objTLSServerConfig,itimeout);
	}
	
	/**
	 * Stops listening on this SCPSession so that new client connection
	 * not accepted and continue to process already connected clients.
	 * @param enumSCPSessionCloseOptions enum specifying option to stop listening.
	 */
	public void stopListening(EnumSCPSessionStopListeningOptions enumSCPSessionStopListeningOptions )
	{		
        if (controller != null)
        {
            if (controller instanceof TLSSCPController)
                ((TLSSCPController)controller).stopListening(enumSCPSessionStopListeningOptions);
            else if ((controller instanceof SCPController) && (enumSCPSessionStopListeningOptions.equals(
              EnumSCPSessionStopListeningOptions.INSECURE)))
            {
                controller.stopListening();
            }
            else
            {
                if (DicomConfig.createInstance().isLoggingOn())
                	DicomLogger.getLogger().log(ResourceBundleWrapper.getValue("warning", "TLSServernotRunning", new Locale(DicomConfig.createInstance().getLocale())));
            }
        }     
	}	

	/**
	 * Closes the TLS SCP Session.
	 */
	@Override
	public void close() 
	{		
		if(DicomConfig.createInstance().isLoggingOn())
		{
			DicomLogger objDicomLogger = DicomLogger.getLogger();
			objDicomLogger.log(ResourceBundleWrapper.getValue("status", "TLSSCPSessionClosed",new Locale(DicomConfig.createInstance().getLocale())));
		}
		
		if(controller != null && (controller instanceof TLSSCPController))
			((TLSSCPController)controller).close();
		else
			controller.close();

		objDefaultAssociation = null;
		objIProcessHandler = null;
	}


}
