package gov.va.med.esr.service.impl;

import gov.va.med.esr.common.model.messaging.ArchivedMessageLogEntry;
import gov.va.med.esr.common.model.messaging.MessageLogEntry;
import gov.va.med.esr.messaging.xml.XmlFormatter;
import gov.va.med.esr.service.MessageFormatterService;
import gov.va.med.fw.hl7.constants.SegmentConstants;
import gov.va.med.fw.util.StringUtils;
import gov.va.med.fw.util.builder.BuilderException;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class MessageFormatterServiceImpl implements MessageFormatterService {

    Map formatterMap = null;
    
    /**
     * An logger instance of log debug information in this class
     */
    private static Log logger = LogFactory.getLog(MessageFormatterServiceImpl.class);
    
    public Map getFormatterMap() {
        return formatterMap;
    }

    public void setFormatterMap(Map formatterMap) {
        this.formatterMap = formatterMap;
    }

    public String getFormattedMessage(MessageLogEntry message) throws BuilderException{
        XmlFormatter formatter = (XmlFormatter) formatterMap.get(message.getType().getCode());
        String messageBody = message.getBody();
        String formattedMessage = null;
        String reformattedMessageBody = null;
        
        //xml validation fails since stored messages have new line characters within a segment hence it was necessary to reformat
        reformattedMessageBody = reformMessageBody(messageBody);
        
        if (messageBody != null )
        {
            formattedMessage = formatter.build(reformattedMessageBody);
        }
        return formattedMessage;
    }
    
    public String getFormattedMessage(ArchivedMessageLogEntry message) throws BuilderException{
        XmlFormatter formatter = (XmlFormatter) formatterMap.get(message.getType().getCode());
        String messageBody = message.getBody();
        String formattedMessage = null;
        String reformattedMessageBody = null;
        
        //xml validation fails since stored messages have new line characters within a segment hence it was necessary to reformat
        reformattedMessageBody = reformMessageBody(messageBody);
        
        if (messageBody != null )
        {
            formattedMessage = formatter.build(reformattedMessageBody);
        }
        return formattedMessage;
    }
    
    public String reformMessageBody(String messageBody) throws BuilderException {

    	StringBuffer reformattedMessageBody = new StringBuffer();


    	try {
    		BufferedReader reader = new BufferedReader(new StringReader(messageBody));
    		String currentLine = null;
    		List segmentsList = Arrays.asList(SegmentConstants.HL7_SEGMENTS_LIST);

    		boolean isSegmentStarted = false;
    		String workingSegment = null;

    		while ((currentLine = reader.readLine()) != null)
    		{
    			if (logger.isDebugEnabled())
    			{
    				logger.debug("Segment: " + currentLine);
    			}

    			//Check if the line starts with one of the predefined segments(e.g MSH, PID, etc)
    			//and if the segment has already started in the previous line

    			if (StringUtils.trim(currentLine).length() >= 3 && segmentsList.contains(currentLine.subSequence(0, 3))
    					&& (!isSegmentStarted) && currentLine.charAt(3)=='^')
    			{
    				isSegmentStarted = true;
    				workingSegment = currentLine;

    			} else if (StringUtils.trim(currentLine).length() >= 3 && segmentsList.contains(currentLine.subSequence(0, 3))
    					&& isSegmentStarted && currentLine.charAt(3)=='^')
    			{
    				//Previous and the current lines are two consecutive segments. Call segment factory to create
    				// the previous one

    				workingSegment = workingSegment + '\n';
    				reformattedMessageBody.append(workingSegment);				        		        
    				isSegmentStarted = true;
    				workingSegment = currentLine;

    			} else if (StringUtils.trim(currentLine).length() < 3 || !segmentsList
    					.contains(currentLine.subSequence(0, 3))
    					&& isSegmentStarted && currentLine.charAt(3)!='^')
    			{
    				//Segment already started in previous lines and this is a wrapped line
    				workingSegment += currentLine;
    			}
    		}
    		reformattedMessageBody.append(workingSegment + '\n');
    	} catch (IOException e) {
    		throw new BuilderException("Invalid message body to build:  " + messageBody + " "
    				+ e.getMessage(), e);
    	}

    	return reformattedMessageBody.toString();

    }

}
