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

import java.io.File;
import java.util.UUID;

import cdac.medinfo.sdk.dcm30_04.enums.EnumCommandField;
import cdac.medinfo.sdk.dcm30_04.enums.EnumItemType;
import cdac.medinfo.sdk.dcm30_04.enums.EnumPDUType;
import cdac.medinfo.sdk.dcm30_04.enums.EnumSOPClassUIDs;
import cdac.medinfo.sdk.dcm30_04.enums.EnumSOPInstanceStatus;


/**
 * This class defines Standard methods used in DICOM protocol
 */
public class StandardMethods
{

	static IPairedCollection<EnumCommandField, EnumCommandField> objExpectedRqRspCollection;

	//static String strOS;
	static String strTempDirPath;
	static 
	{
		//strOS = System.getProperty("os.name");
		strTempDirPath = System.getProperty("java.io.tmpdir");
		if(strTempDirPath.endsWith(File.separator) == false)
			strTempDirPath = strTempDirPath + File.separator;

		objExpectedRqRspCollection = new PairedCollection<EnumCommandField, EnumCommandField>();
		// CServices
		objExpectedRqRspCollection.put(EnumCommandField.C_ECHO_RQ, EnumCommandField.C_ECHO_RSP);
		objExpectedRqRspCollection.put(EnumCommandField.C_FIND_RQ, EnumCommandField.C_FIND_RSP);
		objExpectedRqRspCollection.put(EnumCommandField.C_STORE_RQ, EnumCommandField.C_STORE_RSP);
		objExpectedRqRspCollection.put(EnumCommandField.C_MOVE_RQ, EnumCommandField.C_MOVE_RSP);
		objExpectedRqRspCollection.put(EnumCommandField.C_GET_RQ, EnumCommandField.C_GET_RSP);


		//NServices
		objExpectedRqRspCollection.put(EnumCommandField.N_ACTION_RQ, EnumCommandField.N_ACTION_RSP);
		objExpectedRqRspCollection.put(EnumCommandField.N_CREATE_RQ, EnumCommandField.N_CREATE_RSP);
		objExpectedRqRspCollection.put(EnumCommandField.N_DELETE_RQ, EnumCommandField.N_DELETE_RSP);
		objExpectedRqRspCollection.put(EnumCommandField.N_EVENT_REPORT_RQ, EnumCommandField.N_EVENT_REPORT_RSP);
		objExpectedRqRspCollection.put(EnumCommandField.N_SET_RQ, EnumCommandField.N_SET_RSP);
		objExpectedRqRspCollection.put(EnumCommandField.N_GET_RQ, EnumCommandField.N_GET_RSP);
		/*
		objExpectedRqRspCollection.put( EnumCommandField.C_ECHO_RSP,EnumCommandField.C_ECHO_RQ);
		objExpectedRqRspCollection.put( EnumCommandField.C_FIND_RSP,EnumCommandField.C_FIND_RQ);
		objExpectedRqRspCollection.put( EnumCommandField.C_STORE_RSP,EnumCommandField.C_STORE_RQ);
		objExpectedRqRspCollection.put( EnumCommandField.C_MOVE_RSP,EnumCommandField.C_MOVE_RQ);
		objExpectedRqRspCollection.put( EnumCommandField.C_GET_RSP,EnumCommandField.C_GET_RQ);

		objExpectedRqRspCollection.put( EnumCommandField.N_ACTION_RSP,EnumCommandField.N_ACTION_RQ);
		objExpectedRqRspCollection.put( EnumCommandField.N_CREATE_RSP,EnumCommandField.N_CREATE_RQ);
		objExpectedRqRspCollection.put( EnumCommandField.N_DELETE_RSP,EnumCommandField.N_DELETE_RQ);
		objExpectedRqRspCollection.put( EnumCommandField.N_EVENT_REPORT_RSP,EnumCommandField.N_EVENT_REPORT_RQ);
		objExpectedRqRspCollection.put( EnumCommandField.N_SET_RSP,EnumCommandField.N_SET_RQ);
		objExpectedRqRspCollection.put( EnumCommandField.N_GET_RSP,EnumCommandField.N_GET_RQ);
		 */
	}

	public static EnumCommandField getExpectedCommandField(EnumCommandField enumCommandField)
	{
		if(objExpectedRqRspCollection.contains(enumCommandField))
			return objExpectedRqRspCollection.get(enumCommandField);
		else
			return null;
	}



	/**
	 * Retrieves the temp directory storage path ( "java.io.tmpdir")
	 * @return String - path.
	 */
	public static String getTempDirectoryStorage() 
	{
		return strTempDirPath;
	}

	/**
	 * Retrieves the integer value of VR type.
	 * @param strVRType corresponding string value for VR Type.
	 * @return int - integer value of VR type.
	 */
	public static int getiVRtype(String strVRType) 
	{
		int iVRType = 0;
		try
		{
			if(strVRType == null)
				return DicomConstants.DCM_INVALID_VR;
			if(strVRType.equals("AE"))
			{
				iVRType = DicomConstants.DCM_DT_AE;
			}
			else if(strVRType.equals("AS"))
			{
				iVRType = DicomConstants.DCM_DT_AS;
			}
			else if(strVRType.equals("AT"))
			{
				iVRType = DicomConstants.DCM_DT_AT;
			}
			else if(strVRType.equals("CS"))
			{
				iVRType = DicomConstants.DCM_DT_CS;
			}
			else if(strVRType.equals("DA"))
			{
				iVRType = DicomConstants.DCM_DT_DA;
			}
			else if(strVRType.equals("DS"))
			{
				iVRType = DicomConstants.DCM_DT_DS;
			}
			else if(strVRType.equals("DT"))
			{
				iVRType = DicomConstants.DCM_DT_DT;
			}
			else if(strVRType.equals("FD"))
			{
				iVRType = DicomConstants.DCM_DT_FD;
			}
			else if(strVRType.equals("FL"))
			{
				iVRType = DicomConstants.DCM_DT_FL;
			}
			else if(strVRType.equals("IS"))
			{
				iVRType = DicomConstants.DCM_DT_IS;
			}
			else if(strVRType.equals("LO"))
			{
				iVRType = DicomConstants.DCM_DT_LO;
			}
			else if(strVRType.equals("LT"))
			{
				iVRType = DicomConstants.DCM_DT_LT;
			}
			else if(strVRType.equals("OB"))
			{
				iVRType = DicomConstants.DCM_DT_OB;
			}
			else if(strVRType.equals("OW"))
			{
				iVRType = DicomConstants.DCM_DT_OW;
			}
			else if(strVRType.equals("PN"))
			{
				iVRType = DicomConstants.DCM_DT_PN;
			}
			else if(strVRType.equals("SH"))
			{
				iVRType = DicomConstants.DCM_DT_SH;
			}
			else if(strVRType.equals("SL"))
			{
				iVRType = DicomConstants.DCM_DT_SL;
			}
			else if(strVRType.equals("SQ"))
			{
				iVRType = DicomConstants.DCM_DT_SQ;
			}
			else if(strVRType.equals("SS"))
			{
				iVRType = DicomConstants.DCM_DT_SS;
			}
			else if(strVRType.equals("ST"))
			{
				iVRType = DicomConstants.DCM_DT_ST;
			}
			else if(strVRType.equals("TM"))
			{
				iVRType = DicomConstants.DCM_DT_TM;
			}
			else if(strVRType.equals("UI"))
			{
				iVRType = DicomConstants.DCM_DT_UI;
			}
			else if(strVRType.equals("UL"))
			{
				iVRType = DicomConstants.DCM_DT_UL;
			}
			else if(strVRType.equals("UN"))
			{
				iVRType = DicomConstants.DCM_DT_UN;
			}
			else if(strVRType.equals("US"))
			{
				iVRType = DicomConstants.DCM_DT_US;
			}
			else if(strVRType.equals("UT"))
			{
				iVRType = DicomConstants.DCM_DT_UT;
			}
			else
			{
				iVRType = DicomConstants.DCM_INVALID_VR;
			}
		}
		catch(Exception e)
		{
			if(DicomConfig.createInstance().isLoggingOn())
			{
				DicomLogger.getLogger().log(e.getMessage());
			}
			//e.printStackTrace();
		}
		return iVRType;
	}

	/**
	 * Retrieves the Enum value of SOP Class UID.
	 * @param strSOPClassUID corresponding String value for SOP Class UID.
	 * @return EnumSOPClassUIDs - value of SOP Class UID.
	 */
	public static EnumSOPClassUIDs getSOPClassUID(String strSOPClassUID)
	{
		if(strSOPClassUID == null)
			return null;
		//		 Instead of adding if else blocks, take all values from the enum class and iterate on it.
		EnumSOPClassUIDs[] arrSopClasses = EnumSOPClassUIDs.values();
		for(EnumSOPClassUIDs enumSOPClassUID : arrSopClasses)
		{
			if(strSOPClassUID.equals(enumSOPClassUID.getValue()))
				return enumSOPClassUID;
		}
		return null;		
	}

	/**
	 * Retrieves the Enum value of SOP Class UID.
	 * @param strSOPClassUID corresponding String value for SOP Class UID.
	 * @return EnumSOPClassUIDs - value of SOP Class UID.
	 */
	public static EnumSOPInstanceStatus getSOPInstanceStatus(String strSOPInstanceStatus)
	{
		if(strSOPInstanceStatus == null)
			return null;
		EnumSOPInstanceStatus[] arrSOPInstanceStatus = EnumSOPInstanceStatus.values();
		for(EnumSOPInstanceStatus enumSOPInstanceStatus : arrSOPInstanceStatus)
		{
			if(strSOPInstanceStatus.equals(enumSOPInstanceStatus.getValue()))
				return enumSOPInstanceStatus;
		}
		return null;		
	}

	/**
	 * Retrieves the String value of VR type.
	 * @param iVRType corresponding int value for VR Type.
	 * @return String - String value of VR type.
	 */
	public static String getStrVRtype(int iVRType) 
	{
		switch(iVRType)
		{
		case DicomConstants.DCM_DT_AE :
			return "AE";
		case DicomConstants.DCM_DT_AS :
			return "AS";
		case DicomConstants.DCM_DT_AT :
			return "AT";
		case DicomConstants.DCM_DT_CS :
			return "CS";
		case DicomConstants.DCM_DT_DA :
			return "DA";
		case DicomConstants.DCM_DT_DS :
			return "DS";
		case DicomConstants.DCM_DT_DT :
			return "DT";
		case DicomConstants.DCM_DT_FD :
			return "FD";
		case DicomConstants.DCM_DT_FL :
			return "FL";
		case DicomConstants.DCM_DT_IS :
			return "IS";
		case DicomConstants.DCM_DT_LO :
			return "LO";
		case DicomConstants.DCM_DT_LT :
			return "LT";
		case DicomConstants.DCM_DT_OB :
			return "OB";
		case DicomConstants.DCM_DT_OW :
			return "OW";
		case DicomConstants.DCM_DT_PN :
			return "PN";
		case DicomConstants.DCM_DT_SH :
			return "SH";
		case DicomConstants.DCM_DT_SL :
			return "SL";
		case DicomConstants.DCM_DT_SQ :
			return "SQ";
		case DicomConstants.DCM_DT_SS :
			return "SS";
		case DicomConstants.DCM_DT_ST :
			return "ST";
		case DicomConstants.DCM_DT_TM :
			return "TM";
		case DicomConstants.DCM_DT_UI :
			return "UI";
		case DicomConstants.DCM_DT_UL :
			return "UL";
		case DicomConstants.DCM_DT_UN :
			return "UN";
		case DicomConstants.DCM_DT_US :
			return "US";
		case DicomConstants.DCM_DT_UT :
			return "UT";
		default : 
			return DicomConstants.STRING_INVALID_VR;
		}
	}

	/**
	 * This method creates the hash key with combination of group number and element number.
	 * @param iGroupNumber integer value of group number.
	 * @param iElementNumber integer value of element number.
	 * @return String - String value of HashMap key.
	 */
	public static String createKey(int iGroupNumber, int iElementNumber)
	{
		String strGroupNumber = Integer.toHexString(iGroupNumber);
		String strElementNumber = Integer.toHexString(iElementNumber);
		String strMapKey = strGroupNumber + strElementNumber;
		return strMapKey;
	}

	/**
	 * This method creates the hash key with combination of group number and element number.
	 * @param iGroupNumber integer value of group number.
	 * @param iElementNumber integer value of element number.
	 * @return Integer - integer value of HashMap key.
	 */
	public static Integer createIntKey(int iGroupNumber, int iElementNumber)
	{
		String strGroupNumber = Integer.toHexString(iGroupNumber);
		String strElementNumber = Integer.toHexString(iElementNumber);
		String strMapKey = strGroupNumber + strElementNumber;
		return new Integer(Integer.parseInt(strMapKey));
	}

	/**
	 * This method generates the unique identifier.
	 * @return String - unique identifier.
	 */
	public static String generateUUID()
	{
		String strUUID = null;
		strUUID=UUID.randomUUID().toString();
		return strUUID;
	}

	/**
	 * Gets the command type.
	 * @param shCommandField short value of command field
	 * @return EnumCommandField - The enum Command Filed of short value shCommandField.
	 */
	public static EnumCommandField getCommandType(short shCommandField)
	{
		switch(shCommandField)
		{
		case (short)0x1:
			return EnumCommandField.C_STORE_RQ;
		case (short)0x8001:
			return EnumCommandField.C_STORE_RSP;
		case (short)0x30:
			return EnumCommandField.C_ECHO_RQ;
		case (short)0x8030:
			return EnumCommandField.C_ECHO_RSP;
		case (short)0x0020:
			return EnumCommandField.C_FIND_RQ;
		case (short)0x8020:
			return EnumCommandField.C_FIND_RSP;
		case (short)0x0021:
			return EnumCommandField.C_MOVE_RQ;
		case (short)0x8021:
			return EnumCommandField.C_MOVE_RSP;
		case (short)0x0010:
			return EnumCommandField.C_GET_RQ;
		case (short)0x8010:
			return EnumCommandField.C_GET_RSP;
		case (short)0x0140:
			return EnumCommandField.N_CREATE_RQ;
		case (short)0x8140:
			return EnumCommandField.N_CREATE_RSP;
		case (short)0x0100:
			return EnumCommandField.N_EVENT_REPORT_RQ;
		case (short)0x8100:
			return EnumCommandField.N_EVENT_REPORT_RSP;
		case (short)0x0110:
			return EnumCommandField.N_GET_RQ;
		case (short)0x8110:
			return EnumCommandField.N_GET_RSP;
		case (short)0x0120:
			return EnumCommandField.N_SET_RQ;
		case (short)0x8120:
			return EnumCommandField.N_SET_RSP;
		case (short)0x0130:
			return EnumCommandField.N_ACTION_RQ;
		case (short)0x8130:
			return EnumCommandField.N_ACTION_RSP;
		case (short)0x0150:
			return EnumCommandField.N_DELETE_RQ;
		case (short)0x8150:
			return EnumCommandField.N_DELETE_RSP;
		case (short)0x0FFF:
			return EnumCommandField.C_CANCEL_RQ;
		}
		return null;
	}

	/**
	 * Gets the enum pdu type.
	 * @param b byte value of the PDU type.
	 * @return EnumPDUType - The enum PDU Type of byte value b.
	 */
	public static EnumPDUType getEnumPDUType(byte b)
	{

		switch(b)
		{
		case 0x0001:
			return EnumPDUType.ASSOCIATE_RQ;
		case 0x0002:
			return EnumPDUType.ASSOCIATE_AC;
		case 0x0003:
			return EnumPDUType.ASSOCIATE_RJ;
		case 0x0004:
			return EnumPDUType.P_DATA_TF;
		case 0x0005:
			return EnumPDUType.RELEASE_RQ;
		case 0x0006:
			return EnumPDUType.RELEASE_RP;
		case 0x0007:
			return EnumPDUType.ABORT;
		default :
			return EnumPDUType.NULL;		
		}
	}

	/**
	 * Gets the enum user info item type.
	 * @param bUserInfoItemType byte value of User Info Item Type.
	 * @return EnumItemType - The enum Item Type of byte value b.
	 */
	public static EnumItemType getUserInfoItemType(byte bUserInfoItemType)
	{
		EnumItemType enumEnumItemType = null;
		switch(bUserInfoItemType)
		{
		case (byte)0x0051:
			enumEnumItemType = EnumItemType.USER_INFO_MAX_LENGTH_ITEM;
		break;
		case (byte)0x0052:
			enumEnumItemType = EnumItemType.USER_INFO_IMPL_CLASS_UID_ITEM;
		break;
		case (byte)0x0055:
			enumEnumItemType = EnumItemType.USER_INFO_IMPL_VERSION_NAME_ITEM;
		break;
		case (byte)0x0053:
			enumEnumItemType = EnumItemType.USER_INFO_ASYNC_OPS_WINDOW_ITEM;
		break;
		case (byte)0x0054:
			enumEnumItemType = EnumItemType.USER_INFO_SCU_SCP_ROLE_SELECTION_ITEM;
		break;
		case (byte)0x0056:
			enumEnumItemType = EnumItemType.SOP_CLASS_EXTENDED_NEGOTIATION_ITEM;
		break;
		case (byte)0x0057:
			enumEnumItemType = EnumItemType.SOP_CLASS_COMMON_EXTENDED_NEGOTIATION_ITEM;
		break;
		}
		return enumEnumItemType;
	}	



}
