/********************************************************************
 * Copyright © 2004 EDS. All rights reserved
 ********************************************************************/
//Package
package gov.va.med.esr.messaging.builder.message;

//Java Classes
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.ArrayList;

//Framework Classes
import gov.va.med.fw.service.ServiceException;
import gov.va.med.fw.util.builder.AbstractBuilder;
import gov.va.med.fw.util.builder.BuilderException;
import gov.va.med.fw.hl7.Message;
import gov.va.med.fw.hl7.BatchMessage;
import gov.va.med.fw.hl7.segment.BHS;
import gov.va.med.fw.hl7.segment.BTS;
import gov.va.med.fw.model.AbstractEntity;

//EDB Classes
import gov.va.med.esr.service.MessagingService;

import gov.va.med.esr.messaging.builder.message.BHSBuilder;
import gov.va.med.esr.messaging.builder.message.BTSBuilder;

/**
 * @author Alex Yoon
 * @version 1.0
 */
public class BatchBuilder extends AbstractBuilder {
    /**
    * An instance of serialVersionUID 
    */
   private static final long serialVersionUID = 2243617319564825630L;
   private BHSBuilder bhsBuilder;
	private BTSBuilder btsBuilder;
	private MessagingService messagingService;
	
	/**
	 * The default constructor.
	 * 
	 */
    public BatchBuilder() {
        super();
    }
    
    public BHSBuilder getBhsBuilder()
    {
        return this.bhsBuilder;
    }

    public void setBhsBuilder(BHSBuilder bhsBuilder)
    {
        this.bhsBuilder = bhsBuilder;
    }
    
    public BTSBuilder getBtsBuilder()
    {
        return this.btsBuilder;
    }

    public void setBtsBuilder(BTSBuilder btsBuilder)
    {
        this.btsBuilder = btsBuilder;
    }
    
    public MessagingService getMessagingService()
    {
        return this.messagingService;
    }

    public void setMessagingService(MessagingService messagingService)
    {
        this.messagingService = messagingService;
    }
    
    /**
     * The method that builds the batch message based on passed in messages.
     * 
     * @param message
     *           The parameter object contains list of messages.
     * @return The batch message.
     */	
    public BatchMessage build( Message[] message ) throws BuilderException {
        if((message == null) || 
           (message.length == 0)) {
            throw new BuilderException("Invalid input parameter to build a batch message.");
        }
        
        BatchMessage batchMessage = null;
        List segments = new ArrayList();
        
        try {
	        //Build BHS segment
			segments.add(buildBHSSegment(message[0]));
			
			//Copy over all segment in messages
			//TODO This need to be improved in Iteration 3
			//Implement setMessages(), setBHS(), setBTS() in BatchMessage class.
			for (int i = 0; i < message.length; i++) {
			    segments.addAll(message[i].getSegments());
			}
			
			//Build BTS segment
			segments.add(buildBTSSegment(message.length));
			
			batchMessage = new BatchMessage(segments, message[0].getType(), true);
		}
        catch (Exception e) {
			throw new BuilderException( "Failed to build Batch Message due to an exception ", e );
		}
		        
        return batchMessage;
    }
    
    /**
	 * Method to create BHS segment from data in a message.
	 * 
	 * @param message
	 * 			The message used as source of data for the BHS segment. 
	 * @return The BHS segment.
	 * @throws BuilderException
	 */
	private BHS buildBHSSegment(Message message) throws BuilderException {
	    BHS segment = null;
	    String id;
        
		try {
		    id = this.messagingService.generateControlIdentifier();
		}
		catch (ServiceException se) {
	        throw new BuilderException( "Failed to build BHS segment due to an exception ", se );			
		}
		
		try {
			BHSMetaData metaData = new BHSMetaData((AbstractEntity)null);
			Date creationDatetime = Calendar.getInstance().getTime();
			
			metaData.setControlID(id);
			metaData.setCreationDatetime(creationDatetime);
			metaData.setMessageType(message.getType());
			metaData.setReceivingApplication(message.getReceivingApplication());
			metaData.setReceivingFacility(message.getReceivingFacility());
			
			//Get segment through its builder
			segment = (BHS)(this.bhsBuilder.build(metaData));
		}
		catch (Exception e) {
			throw new BuilderException( "Failed to build BHS Segment due to an exception ", e );
		}
		
		return segment;
	}
	
	/**
	 * Method to create BTS segment from data in a message.
	 * 
	 * @param count
	 * 			The number of messages in a batch. 
	 * @return The BTS segment.
	 * @throws BuilderException
	 */
	private BTS buildBTSSegment(int count) throws BuilderException {
	    BTS segment = null;
	    		
		try {
			BTSMetaData metaData = new BTSMetaData((AbstractEntity)null);
			
			metaData.setMessageCount(count);
			
			//Get segment through its builder
			segment = (BTS)(this.btsBuilder.build(metaData));
		}
		catch (Exception e) {
			throw new BuilderException( "Failed to build BTS Segment due to an exception ", e );
		}
		
		return segment;
	}
}
