/*******************************************************************************
 *  Copyright 2017 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.hl7282.baselibs.parserserializer;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Locale;

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.commoninterface.ICollectionIterator;
import cdac.medinfo.sdk.hl7282.commoninterface.IDelimiter;
import cdac.medinfo.sdk.hl7282.commoninterface.IHL7Stream;
import cdac.medinfo.sdk.hl7282.commoninterface.ISegment;
import cdac.medinfo.sdk.hl7282.commoninterface.ISegmentSet;
import cdac.medinfo.sdk.hl7282.exceptions.DelimiterMissingException;
import cdac.medinfo.sdk.hl7282.exceptions.InvalidDelimiterException;
import cdac.medinfo.sdk.hl7282.exceptions.InvalidFieldException;
import cdac.medinfo.sdk.hl7282.exceptions.InvalidSegmentException;
import cdac.medinfo.sdk.hl7282.exceptions.InvalidSegmentSetException;
import cdac.medinfo.sdk.hl7282.exceptions.SerializeException;
import cdac.medinfo.sdk.hl7282.hl7streams.HL7FileStream;
import cdac.medinfo.sdk.hl7282.utils.EnumSegments;
import cdac.medinfo.sdk.hl7282.utils.HL7Config;
import cdac.medinfo.sdk.hl7282.utils.ResourceBundleWrapper;

/**
 * HL7Serializer serializes the SegmentSet to the stream.
 * SegmentSet is a list of segments which represents a HL7 message. 
 */
public class HL7Serializer 
{
	

	/**
	 * Serializes the SegmentSet on given stream.
	 * @param objSegmentSet instance of SegmentSet
	 * @param objHL7Stream instance of HL7Stream
	 * @return boolean status as true or false
	 * @throws SerializeException if serialization operation fails
	 * @throws IOException if input/output operation fails
	 */
	public boolean serialize(ISegmentSet objSegmentSet,IHL7Stream objHL7Stream)throws SerializeException,IOException
	{
		ICollectionIterator<ISegment> objIterator = objSegmentSet.iterator();
		IDelimiter objIDelimiter = null;
		try
		{
			if(objSegmentSet != null && objSegmentSet.size() != 0)
			{
				ISegment objSegment = objSegmentSet.getSegment(0);

				String strSegmentName = objSegment.getName().getValue();
				String strMsgHeader = EnumSegments.HL7_SEG_MSH.getValue();
				String strBatchHeader = EnumSegments.HL7_SEG_BHS.getValue();
				String strBatchFileHeader = EnumSegments.HL7_SEG_FHS.getValue();


				if(strMsgHeader.equals(strSegmentName) || strBatchHeader.equals(strSegmentName) || strBatchFileHeader.equals(strSegmentName))
				{
					while(objIterator.hasNext())
					{
						objSegment = objIterator.next();

						if(objSegment.getName() == EnumSegments.HL7_SEG_MSH)
							objIDelimiter = ((MSH)objSegment).getDelimiter();
						else if(objSegment.getName() == EnumSegments.HL7_SEG_BHS)
							objIDelimiter = ((BHS)objSegment).getDelimiter();
						else if(objSegment.getName() == EnumSegments.HL7_SEG_FHS)
							objIDelimiter = ((FHS)objSegment).getDelimiter();

						objSegment.serialize(objHL7Stream, objIDelimiter);
					}
				}
				else
					throw new InvalidSegmentSetException(ResourceBundleWrapper.getValue("exceptions", "MissingHeader", new Locale(HL7Config.createInstance().getLocale())));
			}
			else
				throw new InvalidSegmentSetException(ResourceBundleWrapper.getValue("exceptions", "MissingHeader", new Locale(HL7Config.createInstance().getLocale())));
		}
		catch(InvalidSegmentSetException ex)
		{
			throw new SerializeException(this.getClass().getSimpleName(),ex);
		}
		catch(InvalidSegmentException ex)
		{
			throw new SerializeException(this.getClass().getSimpleName(),ex);
		}
		catch(InvalidFieldException ex)
		{
			throw new SerializeException(this.getClass().getSimpleName(),ex);
		}
		catch(InvalidDelimiterException ex)
		{
			throw new SerializeException(this.getClass().getSimpleName(),ex);
		}
		catch(DelimiterMissingException ex)
		{
			throw new SerializeException(this.getClass().getSimpleName(),ex);
		}
		return true;
	}

	/**
	 * Serializes the SegmentSet on given file location.
	 * @param objSegmentSet instance of SegmentSet
	 * @param strFilePath path to file
	 * @return boolean status as true or false
	 * @throws SerializeException if serialization operation fails
	 * @throws IOException if input/output operation fails
	 */
	public boolean serialize(ISegmentSet objSegmentSet,String strFilePath)throws SerializeException,IOException
	{
		FileOutputStream objFileOutputStream = new FileOutputStream(strFilePath);
		HL7FileStream objHL7FileStream = new HL7FileStream();
		objHL7FileStream.setOutputStream(objFileOutputStream);

		boolean bStatus = serialize(objSegmentSet, objHL7FileStream);

		objHL7FileStream.close();

		return bStatus;
	}
}
