package gov.va.med.esr.messaging.service.inbound;

import gov.va.med.esr.messaging.builder.message.BatchBuilder;
import gov.va.med.fw.hl7.BatchMessage;
import gov.va.med.fw.hl7.InvalidMessageException;
import gov.va.med.fw.hl7.Message;
import gov.va.med.fw.hl7.constants.SegmentConstants;
import gov.va.med.fw.hl7.segment.BHS;
import gov.va.med.fw.hl7.segment.MSH;
import gov.va.med.fw.hl7.segment.PID;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.lang.RandomStringUtils;
 
/**
 * Creates a test ORUZ07 data file.
 * 
 * @author Rajiv Patnaik Created on Oct 4, 2006
 * @version 1.0
 * 
 * Copyright © 2006 VHA. All rights reserved
 */
public class CreateORUZ07MessageFileTest extends AbstractCreateHL7MessageFileTest
{
    private static String INPUT_FILE = "ORUZ07TemplateTestData.txt";

    private static String OUTPUT_FILE = "ORUZ07BatchTestData_";
    private static String OUTPUT_FILE_EXT = ".txt";

    private static String MESSAGE_TYPE = "ORUZ07-E";

    /**
     * Total number of new veterans to be included per Batch file
     */
    private static int NEW_VETERANS_MESSAGE_COUNT = 10;

    /**
     * Total number of existing veterans to be included per Batch file
     */
    private static int EXISTING_VETERANS_MESSAGE_COUNT = 0;
    
    /**
     * Total batch files to be created
     */
    private static int TOTAL_FILES = 100;
    
    private static String TEST_SITE = "585";

    private static String QUERY_NEW_VETERANS = "select c.ALTKEY1_TEXT dfn "
            + " from  ps_person_vpid v, ps_person_correlation c,"
            + " ps_system_of_interest_type intr, std_institution inst, person p "
            + " WHERE c.person_vpid_id = v.ps_personvpid_id "
            + " and v.ps_personvpid_id = p.vpid_id and c.system_of_interest_type_id = intr.id  "
            + " and intr.institution_id = inst.id   " 
            + " and c.identifier_type_id = 1507081 " 
            + " and inst.stationnumber='" + TEST_SITE + "'  "
            + " and p.person_id not in(select person_id from enrollment_determination ) "
            + " and rownum <= ROWNUM_COUNT" 
            + " order by p.person_id";

    private static String QUERY_EXISTING_VETERANS = 
        " select c.ALTKEY1_TEXT dfn from ps_person_vpid v,ps_person_correlation c, "
            + "ps_system_of_interest_type intr, "
            + " std_institution inst, person p "
            + " WHERE  c.person_vpid_id = v.ps_personvpid_id and v.ps_personvpid_id = p.vpid_id "
            + " and c.system_of_interest_type_id = intr.id and intr.institution_id = inst.id  " 
            + " and c.identifier_type_id = 1507081 " 
            + "and inst.stationnumber='" + TEST_SITE + "' "
            + " and p.person_id in(select person_id from enrollment_determination ) "
            + " and rownum <= ROWNUM_COUNT"
            + " order by p.person_id ";

    
    /**
     * Creates a Z07 file containing a mix of new and existing veterans
     * 
     * @throws Exception
     */
    public void testCreateData() throws Exception
    {

        int totalNewVets =  TOTAL_FILES * NEW_VETERANS_MESSAGE_COUNT;
        int totalExistingVets =  TOTAL_FILES * EXISTING_VETERANS_MESSAGE_COUNT;
        
        List dfnsNewVeterans = getQueryResults(QUERY_NEW_VETERANS.replaceAll("ROWNUM_COUNT",String.valueOf(totalNewVets)));
        List dfnsExistingVeterans = getQueryResults(QUERY_EXISTING_VETERANS.replaceAll("ROWNUM_COUNT",String.valueOf(totalExistingVets)));

        List chunkedNewVetDfns = chunkDfnsForEachFile(TOTAL_FILES, dfnsNewVeterans);
        List chunkedExistingVetDfns = chunkDfnsForEachFile(TOTAL_FILES, dfnsExistingVeterans);
        
        BatchBuilder batchBuilder = (BatchBuilder) applicationContext
                .getBean("outbound.batchBuilder");
        String data = super.createTestMessageFromFile(INPUT_FILE);

        for (int i = 0; i < TOTAL_FILES; i++)
        {
            List messages = new ArrayList();
            
            createHL7Messages(chunkedNewVetDfns.size() > i ? (String[])chunkedNewVetDfns.get(i): null, data, messages);
            createHL7Messages(chunkedExistingVetDfns.size() > i ?(String[])chunkedExistingVetDfns.get(i):null, data, messages);
            
            Message[] messageArr = new Message[messages.size()];
            int count = 0;
            for (Iterator iter = messages.iterator(); iter.hasNext();)
            {
                Message current = (Message) iter.next();
                messageArr[count++] = current;
            }
		    BatchMessage z07Message = batchBuilder.build(messageArr);
		    
		    /*
		     * must reset sending data to be the TEST_SITE since the BHSBuilder
		     * assumes ESR is sending site (bad in an integrated environment)
		     */
		    BHS bhs = (BHS) z07Message.getSegment(SegmentConstants.BHS);
		    bhs.setSendingApplication("VAMC " + TEST_SITE);
		    bhs.setSendingFacility(TEST_SITE);
		    
		    createTestFile(z07Message, OUTPUT_FILE + i + OUTPUT_FILE_EXT);
        }

    }
    
    private List chunkDfnsForEachFile(int totalFiles, List dfns)
    {
        List chunkedDfns = new ArrayList();
        
        if(dfns == null || dfns.isEmpty())
            return chunkedDfns;
        
        int fileSize = dfns.size()/totalFiles;
        String[] dfnForEachFile = new String[fileSize];
        
        int count = 0;
        for (Iterator iter = dfns.iterator(); iter.hasNext();)
        {
            String dfn = (String) iter.next();
            if(count < fileSize)
            {
                dfnForEachFile[count++] = dfn;
            }else
            {
                chunkedDfns.add(dfnForEachFile);
                dfnForEachFile =new String[fileSize];
                count = 0;
                dfnForEachFile[count++] = dfn;                
            }
        }
        //Add  the last chunk.
        chunkedDfns.add(dfnForEachFile);
        
        return chunkedDfns;
    }
    /**
     * @param dfns
     * @param messageData
     * @param messages
     * @throws InvalidMessageException
     */
    private List createHL7Messages(String[] dfns, String messageData,
            List messages) throws InvalidMessageException
    {
        if(dfns == null)
            return new ArrayList();
        int count = 0;

        for (int i = 0; i < dfns.length; i++)
        {
            String dfn = dfns[i];
            Message message = new Message(messageData, MESSAGE_TYPE);
            PID pid = (PID) message.getSegment(SegmentConstants.PID);
            MSH msh = (MSH) message.getSegment(SegmentConstants.MSH);
            // reset the MessageControlId to be safe
            msh.setControlID(RandomStringUtils.randomNumeric(9));
            pid.setPatientIdentifierList(getPatientIdentifierList(dfn, msh));
            messages.add(message);

            count++;
        }
        
        return messages;
    }

    protected String getPatientIdentifierList(String dfn, MSH msh)
    {
        StringBuffer patientIdentifierList = new StringBuffer();
        //Build DFN
        patientIdentifierList.append(dfn + "~~~"
                + SegmentConstants.ASSIGNING_AUTHORITY_USVHA + "&&"
                + SegmentConstants.ASSIGNING_AUTHORITY_HL7_TABLE + "~"
                + SegmentConstants.IDENTIFIER_TYPE_PI + "~"
                + SegmentConstants.ASSIGNING_LOCATION_VA_FACILITY + "&"
                + msh.getSendingFacility() + "&"
                + SegmentConstants.ASSIGNING_LOCATION_LOCAL_CODING_SCHEME);

        return patientIdentifierList.toString();

    }

    /*
     * (non-Javadoc)
     * 
     * @see gov.va.med.esr.messaging.service.inbound.AbstractCreateHL7MessageFileTest#getOutputFileName()
     */
    protected String getOutputFileName()
    {
        return OUTPUT_FILE;
    }

}