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

import cdac.medinfo.sdk.dcm30_04.services.dicomnetcommons.EnumCommunicationMode;
import cdac.medinfo.sdk.dcm30_04.utils.ICollectionIterator;
import cdac.medinfo.sdk.dcm30_04.utils.ISingleCollection;
import cdac.medinfo.sdk.dcm30_04.utils.SingleCollection;

//TODO: Auto-generated Javadoc
/**
 * The Class implements setters and getters for all required attributes of AgreedAssociation.
 * AgreedAssociation is the state on which calling Entity and called Entity both are agreed.
 * It provides required data related to association which can be useful in over-all process of communication.
 */
public class AgreedAssociation  
{

	/** short value of protocol version. */
	short shProtocolVersion;

	/** string value of called ae title. */
	String strCalledAETitle;

	/** string value of calling ae title. */
	String strCallingAETitle;

	/** string value of application context name. */
	String strAppContextName = null;

	/** agreed presentation context collection. */
	ISingleCollection<AgreedPresContext> objAgreedPresContextCollection = null;;

	/** user info. */
	UserInfo objUserInfo = null;

	/** Enum value of communication mode *. */
	EnumCommunicationMode enumCommMode;

	/** The read max length. */
	int readMaxLength;

	/** The write max length. */
	int writeMaxLength;

	/**
	 * Retrieves the object of agreed presentation context collection.
	 * 
	 * @return ISingleCollection<AgreedPresContext> - collection of AgreedPresContext.
	 */
	public ISingleCollection<AgreedPresContext> getAgreedPresContextCollection() 
	{
		return objAgreedPresContextCollection;
	}

	/**
	 * Sets the obj agreed pres context collection.
	 * 
	 * @param objAgreedPresContextCollection collection of AgreedPresContext.
	 */
	public void setAgreedPresContextCollection(ISingleCollection<AgreedPresContext> objAgreedPresContextCollection) 
	{
		this.objAgreedPresContextCollection = objAgreedPresContextCollection;
	}

	/**
	 * Retrieves the User Information.
	 * 
	 * @return UserInfo - instance of User Information
	 */
	public UserInfo getUserInfo() 
	{
		return objUserInfo;
	}

	/**
	 * Sets the User Information.
	 * 
	 * @param objUserInfo instance of User Information
	 */
	public void setUserInfo(UserInfo objUserInfo)
	{
		this.objUserInfo = objUserInfo;
	}

	/**
	 * Retrieves the mode of Communication.
	 * 
	 * @return EnumCommunicationMode - value of Communication Mode
	 * 1. Asynchronous
	 * 2. Synchronous
	 */
	public EnumCommunicationMode getCommMode() 
	{
		return enumCommMode;
	}

	/**
	 * Sets the mode of Communication.
	 * 
	 * @param enumCommMode Enum value of Communication Mode
	 * 1. Asynchronous
	 * 2. Synchronous
	 */
	public void setCommMode(EnumCommunicationMode enumCommMode) 
	{
		this.enumCommMode = enumCommMode;
	}

	/**
	 * Retrieves the protocol version.
	 * 
	 * @return short - value of protocol version
	 */
	public short getProtocolVersion() 
	{
		return shProtocolVersion;
	}

	/**
	 * Sets the protocol version.
	 * 
	 * @param shProtocolVersion short value of protocol version
	 */
	public void setProtocolVersion(short shProtocolVersion) 
	{
		this.shProtocolVersion = shProtocolVersion;
	}

	/**
	 * Retrieves the Application Context Name.
	 * 
	 * @return String - value of ApplicationContextName.
	 */
	public String getAppContextName() 
	{
		return strAppContextName;
	}

	/**
	 * Sets the Application Context Name.
	 * 
	 * @param strAppContextName String value of ApplicationContextName.
	 */
	public void setAppContextName(String strAppContextName) 
	{
		this.strAppContextName = strAppContextName;
	}

	/**
	 * Retrieves the called Application Entity title.
	 * 
	 * @return String - value of called Application Entity title
	 */
	public String getCalledAETitle() 
	{
		return strCalledAETitle;
	}

	/**
	 * Sets the called Application Entity title.
	 * 
	 * @param strCalledAETitle String value of called Application Entity title
	 */
	public void setCalledAETitle(String strCalledAETitle)
	{
		this.strCalledAETitle = strCalledAETitle;
	}

	/**
	 * Retrieves the calling Application Entity title.
	 * 
	 * @return String - value of calling Application Entity title
	 */
	public String getCallingAETitle()
	{
		return strCallingAETitle;
	}

	/**
	 * Sets the calling Application Entity title.
	 * 
	 * @param strCallingAETitle String value of calling Application Entity title
	 */
	public void setCallingAETitle(String strCallingAETitle) 
	{
		this.strCallingAETitle = strCallingAETitle;
	}

	/**
	 * Retrieves the max length of read.
	 * 
	 * @return int - value of max length
	 */
	public int getReadMaxLength() 
	{
		return readMaxLength;
	}

	/**
	 * Sets the max length of read.
	 * 
	 * @param maxLength int value of maxLength
	 */
	public void setReadMaxLength(int maxLength) 
	{
		readMaxLength = maxLength;
	}

	/**
	 * Retrieves the max length of write.
	 * 
	 * @return int - value of write maxLength
	 */
	public int getWriteMaxLength() 
	{
		return writeMaxLength;
	}

	/**
	 * Sets the max length of write.
	 * 
	 * @param maxLength int value of write maxLength
	 */
	public void setWriteMaxLength(int maxLength) 
	{
		writeMaxLength = maxLength;
	}

	/**
	 * Retrieves the Presentation Context ID for given AbstractSyntaxName if supported else returns -1.
	 * 
	 * @param strAbsSyntax String value of AbstractSyntaxName
	 * 
	 * @return byte - value of PresentationContextID
	 */
	public byte getPresContextID(String strAbsSyntax, String strTS)
	{
		ICollectionIterator<AgreedPresContext> objAgreedPresContextIterator = objAgreedPresContextCollection.iterator();
		AgreedPresContext objAgreedPresContext = null;
		while(objAgreedPresContextIterator.hasNext())
		{
			objAgreedPresContext = objAgreedPresContextIterator.next();
			if(strAbsSyntax.equals(objAgreedPresContext.getAbstractSyntaxName()) && strTS.equals(objAgreedPresContext.getTS()))
			{
				return objAgreedPresContext.getPresContextId();
			}
		}
		return -1;
	}
	
	/**
	 * Retrieves the collection of supported Transfer syntax for SOP Class UID 
	 * @param strAbsSyntax String representing SOP Class UID
	 * @return objTSCollection collection of supported Transfer syntax for SOP Class UID
	 */
	public ISingleCollection<String> getSupportedTSCollection(String strAbsSyntax)
	{
		ISingleCollection<String> objTSCollection = new SingleCollection<String>();
 		ICollectionIterator<AgreedPresContext> objAgreedPresContextIterator = objAgreedPresContextCollection.iterator();
		AgreedPresContext objAgreedPresContext = null;
		while(objAgreedPresContextIterator.hasNext())
		{
			objAgreedPresContext = objAgreedPresContextIterator.next();
			if(strAbsSyntax.equals(objAgreedPresContext.getAbstractSyntaxName()))
			{
				objTSCollection.add(objAgreedPresContext.getTS());
			}
		}
		return objTSCollection;
	}

	/**
	 * Checks the status of SOP class uid whether it is present in Association or not.
	 * 
	 * @param strSOPUid String value of SOP Class UID
	 * 
	 * @return boolean - true If SOP Class is supported by Association Else false
	 */
	public boolean isSOPClassUIDPresent(String strSOPUid)
	{
		if(strSOPUid != null)
		{
			ICollectionIterator<AgreedPresContext> objPresContextIterator = objAgreedPresContextCollection.iterator();
			AgreedPresContext objAgreedPresContext = null;

			while(objPresContextIterator.hasNext())
			{
				objAgreedPresContext = objPresContextIterator.next();
				if(strSOPUid.equals(objAgreedPresContext.getAbstractSyntaxName()))
					return true;
			}
		}
		return false;
	}

	/**
	 * Retrieves the supported TransferSyntax for given Presentation Context ID.
	 * 
	 * @param bPresContextID the b pres context id
	 * 
	 * @return String - value of supported TransferSyntax
	 */
	public String getSupportedTSyntax(byte bPresContextID)
	{
		for(AgreedPresContext objAgreedPresContext : objAgreedPresContextCollection)
		{
			if(objAgreedPresContext.getPresContextId() == bPresContextID)
				return objAgreedPresContext.getTS();
		}

		return null;
	}

//	/**
//	 * Retrieves the first appeared supported TransferSyntax for given SOPClassUID decided at the time of association.
//	 * 
//	 * @param strSOPUid String value of SOPClassUID
//	 * 
//	 * @return String - value of supported TransferSyntax
//	 */
//	public String getSupportedTSyntax(String strSOPUid)
//	{
//		ICollectionIterator<AgreedPresContext> objPresContextIterator = objAgreedPresContextCollection.iterator();
//		AgreedPresContext objAgreedPresContext = null;
//
//		while(objPresContextIterator.hasNext())
//		{
//			objAgreedPresContext = objPresContextIterator.next();
//			if(strSOPUid.equals(objAgreedPresContext.getAbstractSyntaxName()))
//				return objAgreedPresContext.getTS();
//		}
//
//		return null;
//	}

	/**
	 * Defines the mode of communication.
	 * 
	 * @return boolean - mode of communication.
	 * true if communication mode is ASYNCHRONOUS
	 * false if mode is SYNCHRONOUS.
	 */
	public boolean isAsyncMode()
	{
		int maxOpInvoked,maxOpPerformed;

		maxOpInvoked = objUserInfo.getMaxNumOpsInvoked();
		maxOpPerformed = objUserInfo.getMaxNumOpsPerformed();

		/*
		 * If value of both variables is 1 then it shows Synchronous mode else mode is Asynchronous. 
		 * Default mode is Synchronous.
		 */
		if((enumCommMode == EnumCommunicationMode.SYNCHRONOUS) || ((maxOpInvoked == 1) && (maxOpPerformed == 1)))
			return false;
		else
			return true;
	}

	/**
	 * Retrieves the max limit of operations invoked.
	 * 
	 * @return short - value of max capacity.
	 */
	public short getMaxOpsInvoked()
	{
		return objUserInfo.getMaxNumOpsInvoked();
	}

	/**
	 * Retrieves the max limit of operations performed.
	 * 
	 * @return short - value of max capacity.
	 */
	public short getMaxOpsPerformed()
	{
		return objUserInfo.getMaxNumOpsPerformed();
	}

	/**
	 * Sets the max limit of operations invoked.
	 * 
	 * @param maxOpsInvoked value of max capacity.
	 */
	public void setMaxOpsInvoked(short maxOpsInvoked) 
	{
		objUserInfo.setMaxNumOpsInvoked(maxOpsInvoked);
	}

	/**
	 * Sets the max limit of operations Performed.
	 * 
	 * @param maxOpsPerformed value of max capacity.
	 */
	public void setMaxOpsPerformed(short maxOpsPerformed) 
	{
		objUserInfo.setMaxNumOpsPerformed(maxOpsPerformed);
	}

	/**
	 * It checks whether given TS is supported for given SOPClassUID in any of the Presentation Context.
	 * 
	 * @param strSOPClassUID value of SOPClassUID
	 * @param strTransferSyntax value of TransferSyntax
	 * 
	 * @return true If TransferSyntax is supported Else false
	 */
	public boolean isSOPClassUIDSupported(String strSOPClassUID, String strTransferSyntax)
	{
		ISingleCollection<String> objTSCollection = new SingleCollection<String>();
		for(AgreedPresContext objAgreedPresContext : objAgreedPresContextCollection)
		{
			if(strSOPClassUID.equals(objAgreedPresContext.getAbstractSyntaxName()))
				objTSCollection.add(objAgreedPresContext.getTS());
		}
		if(objTSCollection.size() != 0)
		{
			for(String strTS : objTSCollection)
			{
				if(strTS.equals(strTransferSyntax))
					return true;
			}
		}
		return false;
	}


	/**
	 * Gets SOP CLASS EXTENDED NEGOTIATION SUB-ITEM FIELDS for specified SOP Class or Meta SOP Class identifier encoded as a UID.
	 * @param strSOPClassUID value of SOPClassUID
	 * @return instance of Agreed SOP CLASS EXTENDED NEGOTIATION SUB-ITEM FIELDS.
	 */
	public SOPClassExtendedNegotiationSubItemFields getSOPClassExtendedNegotiationSubItemFields(String strSOPClassUID)
	{
		ISingleCollection<SOPClassExtendedNegotiationSubItemFields>  collection = getUserInfo().getSOPClassExtendedNegotiationSubItemFields();
		if(collection != null)
			for (SOPClassExtendedNegotiationSubItemFields fields : collection) 
			{
				if(fields.getSOPClassExtNegotiationSOPclassuid().equals(strSOPClassUID))
					return fields;
			}
		return null;
	}


//	/**
//	* It filters the given DataSetCollection and separate out supported and unsupported DataSets according to Association.
//	* @param objSuppDSCollection Supported DataSet collection.
//	* @param objUnSuppDSCollection UnSupported DataSet Collection
//	* @return boolean - true if min one SOP class UID is supported else false.
//	*/
//	public boolean filter(ISingleCollection<IDataSet> objSuppDSCollection, ISingleCollection<IDataSet> objUnSuppDSCollection)
//	{
//	ICollectionIterator<IDataSet> objDSCollIterator = objSuppDSCollection.iterator();
//	String strSOPUid = null;
//	String strTS = null;
//	IDataSet objIDataSet = null;
//	while(objDSCollIterator.hasNext())
//	{
//	objIDataSet = objDSCollIterator.next();
//	strSOPUid = objIDataSet.getSOPClassUID();
//	if(objIDataSet.getTransferSyntax() != null)
//	strTS = objIDataSet.getTransferSyntax().getTransferSyntaxUID();

//	if(strSOPUid != null && strTS != null)
//	{
//	if(isSOPClassUIDPresent(strSOPUid) && )
//	}
//	}
//	}
}
