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

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

import cdac.medinfo.sdk.dcm30_04.commoninterface.IDataSet;
import cdac.medinfo.sdk.dcm30_04.commoninterface.ITag;
import cdac.medinfo.sdk.dcm30_04.enums.EnumSOPClassUIDs;
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;

/**
 * This class provides implementation of DataBase Connection and processing of queries on DataBase.
 * Print_DBAgent is a singleton class.
 * Print_DBAgent provides the support to create, update and retrieve information of a print SOP Instance
 */
public class Print_DBAgent 
{
	private Print_DBHelper objPrint_DBHelper=null;
	private static String dbURL = null;
	private static String emdriver = null;
	private static Connection objcon = null;
	private static Print_DBAgent objDBAgent = null;
	private static Object mutex = new Object();

	//Default Private Constructor
	private Print_DBAgent(String strConnectionString, String strDriverName)throws SQLException, ClassNotFoundException, InstantiationException, IllegalAccessException
	{
		emdriver = new String(strDriverName);
		dbURL = new String(strConnectionString);
		Class.forName(emdriver).newInstance();
		objcon = DriverManager.getConnection(dbURL);
		objPrint_DBHelper = new Print_DBHelper();
		objPrint_DBHelper.setConnection(objcon);
	}

	/**
	 * Creates instance of Print_DBAgent.
	 * @return Print_DBAgent object of Print_DBAgent
	 * @throws SQLException Signals if SQL Exception occurs.
	 * @throws ClassNotFoundException if ClassNotFoundException occurs
	 * @throws InstantiationException if InstantiationException occurs
	 * @throws IllegalAccessException if IllegalAccessException occurs
	 */
	public static Print_DBAgent createInstance(String strConnectionString, String strDriverName)throws SQLException,ClassNotFoundException, InstantiationException, IllegalAccessException
	{
		synchronized (mutex) 
		{
			if(objDBAgent == null)
				objDBAgent = new Print_DBAgent(strConnectionString,strDriverName);
		}
		return objDBAgent;
	}

	/**
	 * Creates SOP Instance for provided SOPInstanceUID and DataElement attributes.
	 * @param objIDataSet instance of Dataset
	 * @param strSOPInstanceUID value of SOPInstanceUID
	 * @return boolean - status as true or false
	 * @throws SQLException if SQL oparation fails
	 */
	public boolean createSOPInstance(EnumSOPClassUIDs enumSOPClassUIDs, IDataSet objIDataSet,String strSOPInstanceUID)throws SQLException,IOException
	{
		return (objPrint_DBHelper.createSOPInstance(enumSOPClassUIDs,objIDataSet, strSOPInstanceUID));
	}

	/**
	 * This function inserts the values provided in the Relationship table.
	 * @param strBasicFilmSessionSOPInstanceUID String value of Basic Film Session SOP instance.
	 * @param strBasicFilmBoxSOPInstanceUID String value of Basic Film Box SOP instance UID.
	 * @param strImageBoxSOPInstanceUID String value of Image Box SOP instance UID.
	 * @param strBasicAnnotationSOPInstanceUID String value of Basic Annotation SOP instance.
	 * @param strPresentationLUTSOPInstanceUID String value of Presentation LUT SOP instance.
	 * @param strImageOvelaySOPInstanceUID String value of Image Overlay SOP instance.
	 * @return boolean true if the values are inserted properly into Relationship Table.
	 * @throws SQLException Signals if SQL operation fails.
	 */
	public boolean insertIntoRelationShipTable(String strBasicFilmSessionSOPInstanceUID, String strBasicFilmBoxSOPInstanceUID, String strImageBoxSOPInstanceUID, String strBasicAnnotationSOPInstanceUID, String strPresentationLUTSOPInstanceUID, String strImageOvelaySOPInstanceUID) throws SQLException
	{
		return objPrint_DBHelper.insertIntoRelationShipTable(strBasicFilmSessionSOPInstanceUID, strBasicFilmBoxSOPInstanceUID, strImageBoxSOPInstanceUID, strBasicAnnotationSOPInstanceUID, strPresentationLUTSOPInstanceUID,strImageOvelaySOPInstanceUID);

	}

	/**
	 * Updates a SOP Instance
	 * @param objIDataSet instance of Dataset
	 * @param strSOPInstanceUID value of SOPInstanceUID
	 * @return boolean - status as true or false
	 * @throws SQLException if SQL oparation fails
	 */
	public boolean updateSOPInstance(EnumSOPClassUIDs enumSOPClassUIDs,IDataSet objIDataSet,String strSOPInstanceUID)throws SQLException,IOException
	{
		return objPrint_DBHelper.updateInstanceInfo(enumSOPClassUIDs,objIDataSet, strSOPInstanceUID);
	}

	/**
	 * This function updates the Relationship Table.
	 * @param enumSOPClassUIDs EnumValue of SOP Class UID.
	 * @param enumSOPClassUIDOFColumName EnumValue of SOP class UID which is to be updated.
	 * @param strSOPInstance String value of SOP instance UID.
	 * @param strUpdateSOPInstanceUID The new value of SOP instance.
	 * @return boolean return true if the relation ship table is updated successfully. Otherwise false is returned.
	 * @throws SQLException Signals if SQL Exception occurs.
	 */
	public boolean updateRelationShipTable(EnumSOPClassUIDs enumSOPClassUIDs,EnumSOPClassUIDs enumSOPClassUIDOFColumName,String strSOPInstance, String strUpdateSOPInstanceUID) throws SQLException
	{
		return objPrint_DBHelper.updateRelationShipTable(enumSOPClassUIDs,enumSOPClassUIDOFColumName,strSOPInstance,strUpdateSOPInstanceUID);
	}
	/**
	 * Close data base connection.
	 */
	public void close() throws SQLException
	{
		objcon.close();
	}	

	/**
	 * Checks whether provided SOP Instance is created ot not.
	 * @param strSOPInstance value of SOP Instance UID 
	 * @return boolean shows status as success or failure
	 * @throws SQLException if sql operation fails
	 */
	public boolean isSOPInstanceExist(EnumSOPClassUIDs enumSOPClassUIDs,String strSOPInstance)throws SQLException
	{
		return objPrint_DBHelper.isSOPInstanceExist(enumSOPClassUIDs,strSOPInstance);
	}

	/**
	 * This function deletes the SOP Instance Provided.
	 * @param enumSOPClassUIDs EnumValue of SOP Classs UID.
	 * @param strSOPInstance String value of SOP Instance that is to be deleted.
	 * @return boolean - true of the SOP Instance is deleted successfully else return false.
	 * @throws SQLException Signals if the SQL Operation fails.
	 */
	public boolean deleteSOPInstance(EnumSOPClassUIDs enumSOPClassUIDs,String strSOPInstance) throws SQLException
	{
		return objPrint_DBHelper.deleteSOPInstance(enumSOPClassUIDs,strSOPInstance);
	}

	/**
	 * This function retrieves all DataSets related to strSOPInstanceUID.
	 * @param enumSOPClassUIDs
	 * @param objITagCollection  list of requested attributes
	 * @param strSOPInstanceUID String value of SOP instance UID to be retrieved.
	 * @return IDataSet retrieve data set.
	 * @throws SQLException Signals if the SQL operation fails.
	 * @throws IOException Signals if IO Operation fails
	 */
	public IDataSet retrieveSOPInstance(EnumSOPClassUIDs enumSOPClassUIDs, ISingleCollection<ITag> objITagCollection,String strSOPInstanceUID)throws SQLException, IOException
	{
		return objPrint_DBHelper.retrieveSOPInstanceInfo(enumSOPClassUIDs,objITagCollection, strSOPInstanceUID);
	}

	/**
	 * This function gets all the SOP instance UID of EnumSOPClassUIDsToFind related  to SOP Instance UID.
	 * @param enumSOPClassUIDsToFind SOP instance UID of EnumSOPClassUIDsToFind related  to SOP Instance UID.
	 * @param enumSOPClassUIDs Enum SOP Class UID of strValue.
	 * @param strValue String value of SOP Instance UID.
	 * @return String array containg  SOP instance UID of EnumSOPClassUIDsToFind related  to SOP Instance UID.
	 * @throws SQLException Signals if SQL Operation Fails.
	 */
	public String[] getAllSOPInstance(EnumSOPClassUIDs enumSOPClassUIDsToFind, EnumSOPClassUIDs enumSOPClassUIDs,String strValue) throws SQLException
	{
		return objPrint_DBHelper.getAllSOPInstance(enumSOPClassUIDsToFind,enumSOPClassUIDs,strValue);
	}

	/**
	 * This function deletes the Print Job which is specified in the DataSet.
	 * @param enumSOPClassUIDs Enum Value of SOP Class UID.
	 * @param strSOPInstanceUID String value of SOP Instance UID.
	 * @param objIDataSet Data Set containing Print Job ID.
	 * @return boolean true if the Print Job is sucessfully deleted from the DataBase.
	 * @throws IOException Signals if IO Operation fails.
	 * @throws SQLException Signals if SQL Operation fails.
	 */
	public boolean deletePrintJOB(EnumSOPClassUIDs enumSOPClassUIDs,String strSOPInstanceUID , IDataSet objIDataSet) throws IOException, SQLException
	{
		return objPrint_DBHelper.deletePrintJOB(enumSOPClassUIDs, strSOPInstanceUID, objIDataSet);
	}

	/**
	 * This function updates the Priority of Print JOB.
	 * @param enumSOPClassUIDs Enum value of SOP Class UID.
	 * @param strSOPInstanceUID String value of SOP Instance Provided.
	 * @param objIDataSet DataSet containg job id and Priority.
	 * @return boolean true of the Priority of Print Job is modified. Otherfise false is returned.
	 * @throws IOException Signals if the IO Operation fails.
	 * @throws SQLException Signals if the SQL Opeation fails.
	 */
	public boolean updatePrintJob(EnumSOPClassUIDs enumSOPClassUIDs,String strSOPInstanceUID, IDataSet objIDataSet) throws IOException, SQLException
	{
		return objPrint_DBHelper.updatePrintJob(enumSOPClassUIDs, strSOPInstanceUID, objIDataSet);
	}

	/**
	 * Stores the Dataset information into database. 
	 * @param objIDataSet instance of Dataset
	 * @param strSOPInstanceUID value of SOP Instance UID
	 * @return boolean true if successfully inserted else false
	 * @throws SQLException if opeartion failes
	 * @throws ClassNotFoundException if operation failes
	 * @throws InstantiationException if operation failes
	 * @throws IllegalAccessException if operation failes
	 */
	public boolean storeStoredPrintInstanceInfo(IDataSet objIDataSet,String strSOPInstanceUID)throws SQLException,IOException
	{
		if(strSOPInstanceUID != null)
			return objPrint_DBHelper.storeInstanceInfo(objIDataSet,strSOPInstanceUID);
		else
		{
			if(DicomConfig.createInstance().isLoggingOn())
			{
				DicomLogger objDicomLogger = DicomLogger.getLogger();
				objDicomLogger.log(ResourceBundleWrapper.getValue("warning","SOPInstanceUIDNotProvided",new Locale(DicomConfig.createInstance().getLocale())));
			}
			return false;
		}
	}

	/**
	 * Stores the Dataset information into database. 
	 * @param objIDataSet instance of Dataset
	 * @param strSOPInstanceUID value of SOP Instance UID
	 * @return boolean true if successfully inserted else false
	 * @throws SQLException if opeartion failes
	 * @throws ClassNotFoundException if operation failes
	 * @throws InstantiationException if operation failes
	 * @throws IllegalAccessException if operation failes
	 */
	public boolean storeImageInstanceInfo(IDataSet objIDataSet,String strSOPInstanceUID,String strPath)throws SQLException,IOException
	{
		if(strSOPInstanceUID != null)
			return objPrint_DBHelper.storeImageInstanceInfo(objIDataSet,strSOPInstanceUID,strPath);
		else
		{
			if(DicomConfig.createInstance().isLoggingOn())
			{
				DicomLogger objDicomLogger = DicomLogger.getLogger();
				objDicomLogger.log(ResourceBundleWrapper.getValue("warning","SOPInstanceUIDNotProvided",new Locale(DicomConfig.createInstance().getLocale())));
			}
			return false;
		}
	}
}
