package cdac.medinfo.sdk.hl7282.hl7net.commons;

import java.io.ByteArrayInputStream;
import java.io.IOException;

import cdac.medinfo.sdk.hl7282.baselibs.segments.BHS;
import cdac.medinfo.sdk.hl7282.baselibs.segments.FHS;
import cdac.medinfo.sdk.hl7282.baselibs.segments.MSH;
import cdac.medinfo.sdk.hl7282.baselibs.segments.Segment;
import cdac.medinfo.sdk.hl7282.commoninterface.IDelimiter;
import cdac.medinfo.sdk.hl7282.commoninterface.IHL7Stream;
import cdac.medinfo.sdk.hl7282.exceptions.InvalidSegmentException;
import cdac.medinfo.sdk.hl7282.exceptions.ParseException;
import cdac.medinfo.sdk.hl7282.exceptions.SegmentMissingException;
import cdac.medinfo.sdk.hl7282.hl7streams.HL7BufferStream;
import cdac.medinfo.sdk.hl7282.utils.EnumSegments;
import cdac.medinfo.sdk.hl7282.utils.HL7Constants;
import cdac.medinfo.sdk.hl7282.utils.StandardMethods;



/**
 * This class contains some general purpose methods used in the project.
 */
public class StandardUtilityMethods 
{

//	This method checks for the type of Buffer Received i.e which type of message is present
	//it retrieves the type of segment from it and values in it like 
	//In case of Batch BatchControlID and EnumMessageType for BTS segment.
	//In case of BatchFile FileControlID and EnumMessageType for FTS segment.
	
	public static String getControlID(byte[] buffer)throws IOException
	{
		String strMessageControlID;
		byte[] objbyteArray = new byte[buffer.length];
		objbyteArray = buffer;
		HL7BufferStream objErrorHL7BufferStream = new HL7BufferStream();
		ByteArrayInputStream Errorbis = new ByteArrayInputStream(objbyteArray);
		objErrorHL7BufferStream.setInputStream(Errorbis);

		Segment objSegment = getMessageBatchHeader(objErrorHL7BufferStream);
		if(objSegment!=null)
		{
			String strSegment= objSegment.getName().getValue();
			if (strSegment.equals(EnumSegments.HL7_SEG_BHS.getValue()))
			{
				BHS objBHS = (BHS)objSegment;
				strMessageControlID= (String)objBHS.getBatchControlID().getValue();
				return strMessageControlID;
			}
			else if (strSegment.equals(EnumSegments.HL7_SEG_MSH.getValue()))
			{
				MSH objMSH = (MSH)objSegment;
				strMessageControlID =(String)objMSH.getMessageControlID().getValue();
				return strMessageControlID;
			}
		}
		return null;
	}
	/**
	 * 
	 * @param objHL7BufferStream Object of HL7Stream class.
	 * @return Segment of Type MSH,FHS,BHS.
	 * @throws IOException When IOexception fails. 
	 * @throws ParseException when Processing of Stream Fails.
	 */
	public static Segment getMessageBatchHeader(IHL7Stream objHL7BufferStream) throws IOException, ParseException
	{
		try
		{
			Segment objSegment=null;
			IDelimiter objIDelimiter = null;
			StringBuffer strSegmentName = new StringBuffer();
			int iRetVal = 0;
			//Read all bytes from InputStream to buff.
			byte[] buff = new byte[objHL7BufferStream.available()];
			objHL7BufferStream.readBuffer(buff);
			ByteArrayInputStream bis = new ByteArrayInputStream(buff);
			//Reset input stream on IHL7Stream as stream is completely read initially.
			((HL7BufferStream)objHL7BufferStream).setInputStream(bis);
			//Read segment name
			StandardMethods.clearStringBuffer(strSegmentName);
			iRetVal = objHL7BufferStream.readString(strSegmentName,3);
			String strr="";
			char ch= objHL7BufferStream.readChar();
			do
			{	
				strr=strr+ch;
				ch= objHL7BufferStream.readChar();
			}while(ch!='\r');
			
			if((EnumSegments.HL7_SEG_MSH.getValue().equals(strSegmentName.toString()))&& !(iRetVal == HL7Constants.END_OF_STREAM))
			{
				objSegment = new MSH();
				//Parse MSH Segment.
				objSegment.parse(strr, objIDelimiter);
			}
			else if((EnumSegments.HL7_SEG_FHS.getValue().equals(strSegmentName.toString()))&& !(iRetVal == HL7Constants.END_OF_STREAM))
			{
				objSegment = new FHS();
				//Parse FSH Segment.
				objSegment.parse(strr, objIDelimiter);
				iRetVal = objHL7BufferStream.readString(strSegmentName,3);
				if((EnumSegments.HL7_SEG_BHS.getValue()).equals(strSegmentName.toString())&& !(iRetVal == HL7Constants.END_OF_STREAM))
				{
					objSegment = new BHS();
					//Parse MSH Segment.
					objSegment.parse(strr, objIDelimiter);
				}
			}
			else if((EnumSegments.HL7_SEG_BHS.getValue()).equals(strSegmentName.toString())&& !(iRetVal == HL7Constants.END_OF_STREAM))
			{
				objSegment = new BHS();
				//Parse MSH Segment.
				objSegment.parse(strr, objIDelimiter);
			}
			return objSegment;
		}
		catch(SegmentMissingException ex)
		{
			throw new ParseException(ex.getMessage(),ex);
		}
		catch(InvalidSegmentException ex)
		{
			throw new ParseException(ex.getMessage(),ex);
		}
	}
	/**
	 * This method takes object of HL7buffer stream and returns out the byteArrayInputStream by making replica of received stream. 
	 * @param objHL7BufferStream - object of HL7BufferStream
	 * @param byte[] for the received Buffer.
	 * @return byte[] - array of read bytes.
	 */
	public static byte[] createReplicateStream(IHL7Stream objHL7BufferStream,byte[] readBytes)
	{
		HL7BufferStream dummyBufferStream = new HL7BufferStream();
		objHL7BufferStream.readBuffer(readBytes);
		//now objHL7BufferStream is no longer in use
		ByteArrayInputStream dummyByteArrayInputStream = new ByteArrayInputStream(readBytes);
		dummyBufferStream.setInputStream(dummyByteArrayInputStream);
		objHL7BufferStream.reset();
		
		return readBytes;
	}
}
