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

import java.io.IOException;

import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLStreamException;

import cdac.medinfo.sdk.hl7282.exceptions.DumpException;
import cdac.medinfo.sdk.hl7282.exceptions.InvalidSegmentException;
import cdac.medinfo.sdk.hl7282.exceptions.SerializeException;
import cdac.medinfo.sdk.hl7282.unrecognized.UnRecognizedField;
import cdac.medinfo.sdk.hl7282.utils.IMultiValuedPairedCollection;

/**
 * This is Parent Interface of segment in model layer. 
 */
public interface ISegment 
{
	/**
	 * Serializes HL7 Message objects.
	 * Before serialization it validates Message as per HL7 v2.8.2 standard.
	 * For successfully serialization , Message Object should follow order of segments as per its corresponding Message Structure. 
	 * Serialize method fails if given stream is null.
	 * It mandates presence of required segments and the number of occurrences specified by the standard.
	 * This method also checks for presence of Mandatory Groups.It also verifies repeatability of Group.
	 * @param objIHL7Stream Object of HL7Stream class
	 * @param objIDelimiter Object of Delimiter class present as inner class in MSG class
	 * @return int - function status [success/failure]
	 * @throws SerializeException Thrown when serialization of Message fails
	 * @throws IOException Signals that an I/O exception of some sort has occurred
	 */
	int serialize(IHL7Stream objIHL7Stream,IDelimiter objIDelimiter) throws IOException;
	

	/**
	 * Validates HL7 Message objects .
	 * Validate method checks for validation each and every segments in side the Message object against specified message Structure. 
	 * Validation checks include optionality of segment or group.
	 * It also verifies the number of times segment or group is repeated in message.
	 * e.g 
	 * {PSH} while parsing PSH segment validate method will check for its mandatory presence.
	 * [PSH] in this case validate will throw exception if one tries to enter more than one PSH segment.
	 * @return boolean - true or false
	 * @throws InvalidSegmentException Throws when Segment Validation fails
	 */
	boolean validate();
	

	/**
	 * Parses HL7 Segment Strings from any Stream into HL7 Segment object.
	 * This method checks for the Repetition of the fields in the Segment.
	 * It also checks for the optionality of the fields as whether they are mandatory or optional.
	 * Successful parsing of the segment populates the object with the data present on the stream and provides
	 * easy accessor and mutator methods to navigate the message.
	 * It also leads to failure if version of given HL7 Message is not 2.8.2.
	 * This method raises exception if there is Segment which is not valid as per HL7 v 2.8.2 standard.
	 * @param strHL7segmentString Object of HL7Stream
	 * @param objIDelimiter Object of class Delimiter
	 * @return int - Success if segment is valid
	 * 			   - Fail if segment in not valid
	 * @throws InvalidSegmentException Thrown when Segment Validation Fails
	 * @throws IOException Signals that an I/O exception of some sort has occurred
	 */
	int parse(String strHL7segmentString,IDelimiter objIDelimiter) throws IOException;

	/**
	 * Returns Segment Name.
	 * @return EnumSegments - enum used for SegmentName
	 */
	ISegmentKey getName();
	
	/**
	 * Sets Segment Name.
	 * @param enumName	 
	 */
	void setName(ISegmentKey enumName);
	

	/**
	 * Moves to next Segment.
	 * @param strFieldStream String from HL7Stream
	 */

	public void moveToNextSegment(String strFieldStream);
	
    /**
     * Dumps information of segments like Attribute Name and its value.
	 * @param objIHL7Stream Object of HL7Stream class
     * @param objIDelimiter Object of IDelimiter
	 */
	void dumpSegment(IHL7Stream objIHL7Stream,IDelimiter objIDelimiter, int iLevel)throws DumpException,IOException;
	
	/**
	 * Removes Data Element from Data Element List.
	 * @param strAttributeName String value of Attribute Name
	 * @return True - if attrbute removed successfully, else returns false
	 */
	int removeDataElement(String strAttributeName, boolean isForcefullyRemove);
	
	/**
	 * Removes Data Element from Data Element List.
	 * @param iItemIDToBeRemoved Integer value for attribute which is Item ID specified by HL7
	 * @return True - if attrbute removed successfully, else returns false
	 */
	int removeDataElement(int iItemIDToBeRemoved, boolean isForcefullyRemove);
	
	/**
	 * Updates Data Element from Data Element List.
	 * @param iItemIDToBeRemoved Integer value for attribute which is Item ID specified by HL7
	 * @param objIHL7Stream Object of IHL7Stream
	 * @param objDelimiter Object of IDelimiter
	 * @return True - if attribute removed successfully, else returns false
	 */
	int updateDataElement(int iItemIDToBeUpdated, String strSegmentString , IDelimiter objDelimiter)throws IOException;

	/**
	 * Updates Data Element from Data Element List.
	 * @param iItemIDToBeUpdated Integer value for attribute which is Item ID specified by HL7
	 * @param objIDataType Object of DataType
	 * @return True - if attribute removed successfully, else returns false
	 */
	int updateDataElement(int iItemIDToBeUpdated, IDataType objIDataType)throws IOException;

	/**
	 * Get the Fields collection of Segment
	 * @return ISingleCollection&lt;Integer, IDataType&gt; - Collection of DataType of the Segment.
	 */
	IMultiValuedPairedCollection<Integer, IDataType> getFields();

	/**
	 * Writes the data to the Stream.
	 * @param XMLEventWriter Object of XMLEventWriter
	 * @return int - Success or failure of the read
	 * @throws IOException - if  IO operation fails 
	 * @throws XMLStreamException - The base exception for unexpected processing errors. This Exception class is used to report well-formed errors as well as unexpected processing conditions. 
	 */
	int writeToXML(XMLEventWriter eventWriter) throws IOException, XMLStreamException;
	 
	/**
	 * Writes the data to the Stream.
	 * @param XMLEventWriter Object of XMLEventWriter
	 * @return int - Success or failure of the read
	 * @throws IOException - if  IO operation fails 
	 * @throws XMLStreamException - The base exception for unexpected processing errors. This Exception class is used to report well-formed errors as well as unexpected processing conditions. 
	 */
	int writeToXML_v2(XMLEventWriter eventWriter) throws IOException, XMLStreamException;
	
	/**
	 * Adds UnRecognizedField in list.
	 * @param objUnRecognizedField object of UnRecognizedField
	 */
	public void addUnRecognizedField(UnRecognizedField objUnRecognizedField);
	
	/**
	 * Retrieves list of Unrecognized field.
	 * @return Isinglecollection<UnRecognizedField> - list of UnRecognized field
	 */
	public ISingleCollection<UnRecognizedField> getUnrecognizedFields();
	
}
