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

import java.io.ByteArrayOutputStream;
import java.io.IOException;

import cdac.medinfo.sdk.dcm30_04.commoninterface.IDicomStream;
import cdac.medinfo.sdk.dcm30_04.dicomstreams.DicomBufferStream;
import cdac.medinfo.sdk.dcm30_04.exceptions.ParseException;
import cdac.medinfo.sdk.dcm30_04.utils.ICollectionIterator;
import cdac.medinfo.sdk.dcm30_04.utils.ISingleCollection;
import cdac.medinfo.sdk.dcm30_04.utils.SingleCollection;

/**
 * This Class  represents P_DATA_TF_PDU.
 */
public  class P_DATA_TF_PDU extends PDU 
{

	/** boolean variable representing last data fragment. */
	private boolean isLastDataFragment = false;

	/** boolean variable representing last command fragment. */
	private boolean isLastCommandFragment = false;

	/** The collection of P-DATA-VALUE-ITEM */
	ISingleCollection<P_DATA_ValueItem> objISinColPdataValueItem = null;

	/**
	 * Instantiates a new P-DATA-TF-PDU.
	 */
	public P_DATA_TF_PDU()
	{
		objISinColPdataValueItem = new SingleCollection<P_DATA_ValueItem>();
	}

	/**
	 * Sets the PDV item collection.
	 * @param objISinColPdataValueItem
	 */
	public void setPDVItemCollection(ISingleCollection<P_DATA_ValueItem> objISinColPdataValueItem)
	{
		this.objISinColPdataValueItem = objISinColPdataValueItem;
	}

	/**
	 * The implementation of this method parse the P Data TF PDU from the
	 * given Stream.
	 * @param objIDicomStream Stream on which the DICOM data is available.
	 * @throws IOException Signals that an IO Exception has occurred.
	 * @throws ParseException Signals that Parse Exception has occurred.
	 */
	public void parse(IDicomStream objIDicomStream) throws IOException
	{
		super.parse(objIDicomStream);

//		objIDicomStream.readInt();
		while(objIDicomStream.available() != 0)
		{
			P_DATA_ValueItem objPDataValueItem = new P_DATA_ValueItem();
			objPDataValueItem.parse(objIDicomStream);
			objISinColPdataValueItem.add(objPDataValueItem);
		}
	}

	/**
	 * The implementation of this method serialize the P Data TF PDU from
	 * the given Stream.
	 * @param objIDicomStream Stream on which the DICOM data is available.
	 * @throws IOException Signals that an IO Exception has occurred.
	 */
	public void serialize(IDicomStream objIDicomStream) throws IOException
	{
		super.serialize(objIDicomStream);
		ICollectionIterator<P_DATA_ValueItem> objICollectionIterator = objISinColPdataValueItem.iterator();
		while(objICollectionIterator.hasNext())
		{
			P_DATA_ValueItem objPValueItem = objICollectionIterator.next();
			objPValueItem.serialize(objIDicomStream);
		}
	}

	/**
	 * This function gets the length of P-Data-Value-ITem.
	 */
	public int getLength()
	{
		int iP_Data_tf_pdu_len = 0;
		ICollectionIterator<P_DATA_ValueItem> objICollectionIterator = objISinColPdataValueItem.iterator();
		while(objICollectionIterator.hasNext())
		{
			P_DATA_ValueItem objPValueItem = objICollectionIterator.next();
			iP_Data_tf_pdu_len += EnumLength.PDV_ITEM_HEADER_LENGTH.getIntValue() 
			+ EnumLength.PDV_HEADER_LENGTH.getIntValue() + objPValueItem.getPDV().getFragment().length;
		}
		return iP_Data_tf_pdu_len;
	}

	/**
	 * Gets the all command fragments.
	 * @return byte[] - byte array containing  all command fragments in PDU.
	 * @throws IOException  Signals that an I/O exception has occurred.
	 */
	public byte[] getAllCommmandFragments() throws IOException
	{
		DicomBufferStream objDicomBufferStream = new DicomBufferStream();
		ByteArrayOutputStream objByteArrayOutputStream = new ByteArrayOutputStream();
		objDicomBufferStream.setOutputStream(objByteArrayOutputStream);
		ICollectionIterator<P_DATA_ValueItem> objIterator = objISinColPdataValueItem.iterator();
		while(objIterator.hasNext())
		{
			P_DATA_ValueItem objPValueItem = objIterator.next();
			PDV objPDV = objPValueItem.getPDV();
			if(objPDV.getFragmentType() == 1)
			{
				if(objPDV.isLast())
					isLastCommandFragment = true;
				objDicomBufferStream.writeBuffer(objPDV.getFragment(), 0, objPDV.getFragment().length);
			}
		}
		return objByteArrayOutputStream.toByteArray();
	}

	/**
	 * Gets all data fragments.
	 * @return byte[] - byte array containing all data fragments
	 * @throws IOException  Signals that an I/O exception has occurred.
	 */
	public byte[] getAllDataFragments() throws IOException
	{
		DicomBufferStream objDicomBufferStream = new DicomBufferStream();
		ByteArrayOutputStream objByteArrayOutputStream = new ByteArrayOutputStream();
		objDicomBufferStream.setOutputStream(objByteArrayOutputStream);
		ICollectionIterator<P_DATA_ValueItem> objIterator = objISinColPdataValueItem.iterator();
		while(objIterator.hasNext())
		{
			P_DATA_ValueItem objPValueItem = objIterator.next();
			PDV objPDV = objPValueItem.getPDV();
			if(objPDV.getFragmentType() == 0)
			{
				if(objPDV.isLast())
					isLastDataFragment = true;
				objDicomBufferStream.writeBuffer(objPDV.getFragment(), 0, objPDV.getFragment().length);
			}
		}
		return objByteArrayOutputStream.toByteArray();
	}

	/**
	 * Checks whether last data fragment present.
	 * @return true, if is last data fragment present
	 */
	public boolean isLastDataFragmentPresent()
	{
		return isLastDataFragment;
	}

	/**
	 * Checks if last command fragment is present.
	 * @return true, if is last command fragment present
	 */
	public boolean isLastCommandFragmentPresent()
	{
		return isLastCommandFragment;
	}

	/**
	 * Retrieves the fragment type whether it is Command fragment or DataSet fragment.
	 * @return int -   if 1 fragment type is CommandSet
	 * 				   if 0 fragment type is DataSet
	 * 				   if -1 no value present
	 */
	public int getFragmentType()
	{
		if(objISinColPdataValueItem != null)
		{
			P_DATA_ValueItem objPItem = objISinColPdataValueItem.elementAt(0);
			if(objPItem != null)
			{
				PDV objpdv = objPItem.getPDV();
				if(objpdv != null)
					return objpdv.getFragmentType();
			}
		}
		return -1;
	}
	
	/**
	 * Retrieves the Presentation Context ID from Presentation Data Value Items.
	 * @return byte - value of PresentationContextID 
	 */
	public byte getPresContextID()
	{
		if(objISinColPdataValueItem != null)
		{
			P_DATA_ValueItem objPItem = objISinColPdataValueItem.elementAt(0);
			if(objPItem != null)
			{
				return objPItem.getPresentationContextID();
			}
		}
		return -1;
	}
}
