/********************************************************************
 * Copyright © 2004 VHA. All rights reserved
 ********************************************************************/
package gov.va.med.fw.hl7;

// Java classes
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;

//Framework Classes
import gov.va.med.fw.hl7.constants.SegmentConstants;

/**
 * @author Vu Le
 * @version 1.0
 */
public class BatchMessage extends Message {

   /**
	 * An instance of serialVersionUID
	 */
	private static final long serialVersionUID = -2971553257449340578L;

	private List messages = null;
   
   //private List batchSegments = null;
   
   /**
    * Comment for <code>mappings</code>
    */
   private HashMap mappings = null;
   
   
   /**
    * A default constructor 
    */
   public BatchMessage() {
      super();
   }
   
   /**
    * @param segments
    * @throws InvalidMessageException
    */
   public BatchMessage(List segments) throws InvalidMessageException {
      super(segments, null);
   }
   /**
    * @param segments
    * @param type
    * @throws InvalidMessageException
    */
   public BatchMessage(List segments, String type) throws InvalidMessageException {
      super(segments, type);
   }
   
   /**
    * @param segments
    * @param type
    * @param wrapSegmentData - Flag to indicate if a segment data needs
    * 		 to be wrapped into multiple lines if it exceeds a certain limit. 
    *       This constructor will mostly be called when the message data needs 
    * 		 to be sent to outbound Vista sites.	    
    * @throws InvalidMessageException
    */
   public BatchMessage(List segments, String type, boolean wrapSegmentData) throws InvalidMessageException {
      super(segments, type, wrapSegmentData);
   }   
    
   /**
    * @param data
    * @throws InvalidMessageException
    */
   public BatchMessage(String data) throws InvalidMessageException {
      this(data, null);
   }
   /**
    * @param data
    * @param type
    * @throws InvalidMessageException
    */
   public BatchMessage(String data, String type) throws InvalidMessageException {
      super(data, type);
   }
   
   /**
    * @return Returns the mappings.
    */
   public HashMap getMappings() {
      return mappings;
   }
   
   /**
    * @param mappings The mappings to set.
    */
   public void setMappings(HashMap mappings) {
      this.mappings = mappings;
   }
   
   public Segment getHeader() throws InvalidMessageException {
      return getSegment( SegmentConstants.BHS );
   }

   public Segment getTrailer() throws InvalidMessageException {
      return getSegment( SegmentConstants.BTS );
   }
   
   public String getMessageID() throws InvalidMessageException {
      
      String value = null;
      Segment header = getHeader();
      if( header != null ) {
         // get a list of elements to get batch id
         // which is the 11th element 
         List elements = header.getElements();
         if( elements != null && elements.size() >= 11 ) {
            value = (String)elements.get( 10 );
         }
      }
      return value;
   }

   public String getMessageType() throws InvalidMessageException {
      
      String value = null;
      Segment header = getHeader();
      if( header != null ) {
         // get a list of elements to get batch type
         // which is the 9th element 
         List elements = header.getElements();
         if( elements != null && elements.size() >= 9 ) {
            value = (String)elements.get( 8 );
         }
      }
      return value;
   }
   
   public String getSendingApplication() throws InvalidMessageException {
      
      String value = null;
      Segment header = getHeader();
      if( header != null ) {
         // get a list of elements to get a sending application
         // which is the 3rd element 
         List elements = header.getElements();
         if( elements != null && elements.size() >= 3 ) {
            value = (String)elements.get( 2 );
         }
      }
      return value;
   }
   
   public String getSendingFacility() throws InvalidMessageException {
    
   	  String value = null;
      Segment header = getHeader();
      if( header != null ) {
         // get a list of elements to get a sending facility
         // which is the 4th element 
         List elements = header.getElements();
         if( elements != null && elements.size() >= 4 ) {
            value = (String)elements.get( 3 );
         }
      }
      return value;
   }
   
   public String getReceivingApplication() throws InvalidMessageException {
      
      String value = null;
      Segment header = getHeader();
      if( header != null ) {
         // get a list of elements to get a receiving application
         // which is the 5th element 
         List elements = header.getElements();
         if( elements != null && elements.size() >= 5 ) {
            value = (String)elements.get( 4 );
         }
      }
      return value;
   }
   
   public String getReceivingFacility() throws InvalidMessageException {
    
   	  String value = null;
      Segment header = getHeader();
      if( header != null ) {
         // get a list of elements to get a receiving facility
         // which is the 6th element 
         List elements = header.getElements();
         if( elements != null && elements.size() >= 6 ) {
            value = (String)elements.get( 5 );
         }
      }
      return value;
   }
   
   /* (non-Javadoc)
    * @see com.VHA.fw.message.Message#getSegments()
    *//*
    * 
    * Commented out RP 09/07. 
    * This was overiding the method in the superclass to return just
    * the BatchSegments i.e BHS and BTS. This was causing problems when trying
    * to search a different segment like MSH in the BatchMessage as it would
    * not show in the list of segments. This method does not seem to be used
    * anywhere right now. If needed, we can uncomment this out and deal with 
    * the other problem differently.
   public List getSegments() throws InvalidMessageException {
      
      if( batchSegments == null ) {
         synchronized( this ) {
            List segments = super.getSegments();
            if( segments != null && !segments.isEmpty() ) {
               batchSegments = new ArrayList();
               
               // Add the first segment BHS and last segment
               // BTS in a batch segment list
               batchSegments.add( segments.get( 0 ) );
               batchSegments.add( segments.get( segments.size() - 1 ) );
            }
         }
      }
      return batchSegments;
   }*/
   
   public List getMessages() throws InvalidMessageException  {
      if( messages == null ) {
         synchronized( this ) {
            
            // Call a getSegments method in a message class
            // to get all the message segments
            List segments = super.getSegments();
               
            Segment s = getSegment( segments, SegmentConstants.BHS );
            if( s == null ) {
               throw new InvalidMessageException( "Missing batch header segment" );
            }
               
            s = getSegment( segments, SegmentConstants.BTS );
            if( s == null ) {
               throw new InvalidMessageException( "Missing batch trailer segment" );
            }
               
            // Create a list of messages
            messages = new ArrayList();

            // build a list of segments to pass to a message
            int count = segments.size();
            ArrayList msgSegments = new ArrayList();
            
            // Skip the first BHS segment and the last BTS segment
            for( int i=1; i<(count - 1); i++ ) {
               s = (Segment)segments.get( i );
               if( s.getName().equals( "MSH" ) && !msgSegments.isEmpty() ) {
                  messages.add( createMessage( msgSegments ) );
                  msgSegments = new ArrayList();
               }
               msgSegments.add( s );
            }
               
            // This is to handle the last message in the batch
            if( !msgSegments.isEmpty() ) {
               messages.add( createMessage( msgSegments ) );
            }
         }
      }
      return messages;
   }
   
   protected Message createMessage( ArrayList data ) throws InvalidMessageException {
      return new Message( data, getType() );
   }
}