

package gov.va.med.cds.testharness.vhim400.builders;


import org.apache.commons.logging.Log;
import org.apache.logging.log4j.Logger;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;


public class HAVitalsBuilder
    extends
        AbstractEntryPointBuilder
{
    protected static Log logger = null;
    public static final String LOGGER_CONFIG_PATH = "log4j.properties";
    private static final int RECORD_VERSION = 12345;
    private String recordIdentifierIdentity;
    private String[] qualifierRecordIdentifiers;

    private int IDX;

    public static final String[] OBSERVATION_METHODS = { "Method 1", "Method 2", "Method 3", "Method 4" };
    public static final String[] OBSERVED_CHARACTERITICS = { "Characteristic 1", "Characteristic 2", "Characteristic 3", "Characteristic 4" };
    public static final String[] QUALIFIERS_OLD = { "Qualifier-1", "Qualifier-2", "Qualifier-3", "Qualifier-4" };
    public static final String[][] QUALIFIERS = { {"4688703", "SITTING", "99VA120.52"}, {"4500643", "STANDING", "99VA120.52"}, {"4688663", "LYING", "99VA120.52"}, {"4500642", "ORAL", "99VA120.52"} };
    
    public HAVitalsBuilder( )
    {
        super();
    }


    public HAVitalsBuilder( Random random )
    {
        super( random );
    }


    public HAVitalsBuilder( String recordIdentifierIdentity )
    {
        super();
        this.recordIdentifierIdentity = recordIdentifierIdentity;

    }
    
    public HAVitalsBuilder( String recordIdentifierIdentity, String[] qualifierRecordIdentifiers )
    {
        super();
        this.recordIdentifierIdentity = recordIdentifierIdentity;
        this.qualifierRecordIdentifiers = qualifierRecordIdentifiers;

    }


    public List<Element> makeVitals( int number )
    {
        return makeVitals( number, null );
    }


    public List<Element> makeVitals( int number, Element patient )
    {
        return makeVitals( number, patient, true );

    }


    public List<Element> makeVitals( int number, Element patient, boolean updateRecordXml )
    {
        List<Element> vitals = new ArrayList<Element>( number );
        for ( int i = 0; i < number; i++ )
        {
            vitals.add( makeVital( "vitalSignObservationEvent", patient, updateRecordXml ) );
        }
        return vitals;

    }


    public Element createEntryPointRecord( Element personIdentifier )
    {
        return makeVital( "vitalSignObservationEvent", personIdentifier );
    }


    public Element makeVital( String elementName, Element patientIdentifier )
    {
        return makeVital( elementName, patientIdentifier, false );
    }


    /*
    <xsd:complexType name="VitalSignObservationEvent">
    <xsd:sequence>
      <xsd:element name="recordIdentifier" type="basedatatypes:HL72EntityIdentifier"/>
      <xsd:element name="patient" type="common:PatientLite"/>
      <xsd:element minOccurs="0" name="observationTime" type="basedatatypes:PointInTime"/>
      <xsd:element minOccurs="0" name="observationMethod" type="basedatatypes:HL72CodedElementLite"/>
      <xsd:element minOccurs="0" name="observedCharacteristic" type="basedatatypes:HL72CodedElementLite"/>
      <xsd:element minOccurs="0" name="collectionSessionTime" type="basedatatypes:PointInTime"/>
      <xsd:element minOccurs="0" name="status" type="xsd:string"/>
      <xsd:element minOccurs="0" name="supplementalOxygen" type="vitalsigns:OxygenAdministration"/>
      <xsd:element minOccurs="0" name="author" type="common:PractitionerParticipationLite"/>
      <xsd:element minOccurs="0" name="homeTelehealthMonitor" type="vitalsigns:HomeTelehealthMonitor"/>
      <xsd:element minOccurs="0" name="hospitalLocationIdentifier" type="basedatatypes:HL72LocationIdentifier"/>
      <xsd:element minOccurs="0" name="division" type="basedatatypes:HL72CodedElementLite"/>
      <xsd:element minOccurs="0" name="orderingFacilityIdentifier" type="basedatatypes:HL72OrganizationIdentifier"/>
      <xsd:element minOccurs="0" name="stopCode" type="basedatatypes:HL72CodedElementLite"/>
      <xsd:element minOccurs="0" name="vitalSignObservation" type="vitalsigns:VitalSignObservation"/>
      <xsd:element minOccurs="0" name="errorEnterer" type="common:PractitionerParticipationLite"/>
      <xsd:element maxOccurs="unbounded" minOccurs="0" name="errorReason" type="vitalsigns:ErrorReason"/>
      <xsd:element minOccurs="0" name="recordSource" type="basedatatypes:HL72FacilityIdentifier"/>
      <xsd:element name="recordVersion" type="xsd:int"/>
      <xsd:element name="recordUpdateTime" type="basedatatypes:PointInTime"/>
    </xsd:sequence>
    </xsd:complexType>
     */
    public Element makeVital( String elementName, Element patientIdentifier, boolean updateRecordXml )
    {
        IDX++ ;

        Element newVitalSignObservationEvent = DocumentHelper.createElement( elementName );

        Element newPatient = createPatientLite( "patient" );
        if ( patientIdentifier != null )
        {
            newPatient.element( "identifier" ).element( "identity" ).setText( patientIdentifier.elementText( "identity" ) );
            newPatient.element( "identifier" ).element( "assigningFacility" ).setText( patientIdentifier.elementText( "assigningFacility" ) );
            newPatient.element( "identifier" ).element( "assigningAuthority" ).setText( patientIdentifier.elementText( "assigningAuthority" ) );
        }
        newVitalSignObservationEvent.add( newPatient );

        if ( updateRecordXml )
        {
            if ( this.recordIdentifierIdentity != null )
            {
                newVitalSignObservationEvent.add( createHL72EntityIdentifier( "recordIdentifier", this.recordIdentifierIdentity ) );
            }
            else
            {
                newVitalSignObservationEvent.add( createHL72EntityIdentifier( "recordIdentifier", IDX ) );
            }

        }

        Element newObservationTime = createFixedPointInTime( "observationTime" );
        newVitalSignObservationEvent.add( newObservationTime );

        Element newObservationMethod = createHL72CodedElementLite( "observationMethod", "ObservationMethod", OBSERVATION_METHODS );
        newVitalSignObservationEvent.add( newObservationMethod );

        Element newObservedCharacteristic = createHL72CodedElementLite( "observedCharacteristic", "ObservedCharacteristic", OBSERVED_CHARACTERITICS );
        newVitalSignObservationEvent.add( newObservedCharacteristic );

        Element newCollectionSessionTime = createFixedPointInTime( "collectionSessionTime" );
        newVitalSignObservationEvent.add( newCollectionSessionTime );

        newVitalSignObservationEvent.addElement( "status" ).addText( "Status" );

        Element newSupplementalOxygen = makeOxygenAdministration( "supplementalOxygen" );
        newVitalSignObservationEvent.add( newSupplementalOxygen );

        Element newHomeTelehealthMonitor;
        if ( updateRecordXml && this.recordIdentifierIdentity != null )
        {
            newHomeTelehealthMonitor = makeHomeTelehealthMonitor( "homeTelehealthMonitor", updateRecordXml );
        }
        else
        {
            newHomeTelehealthMonitor = makeHomeTelehealthMonitor( "homeTelehealthMonitor" );
        }
        newVitalSignObservationEvent.add( newHomeTelehealthMonitor );

        Element newVitalSignObservation = makeVitalSignObservation( "vitalSignObservation" );
        newVitalSignObservationEvent.add( newVitalSignObservation );

        /*Element newRecordSource = createHL72FacilityIdentifier("recordSource");
        newVitalSignObservationEvent.add( newRecordSource );

        newVitalSignObservationEvent.addElement("recordVersion").addText( RECORD_VERSION +"");

        Element newRecordUpdateTime = createPointInTime("recordUpdateTime");
        newVitalSignObservationEvent.add( newRecordUpdateTime );*/

        return newVitalSignObservationEvent;
    }

    /*unused build method - but in place for Fall 2012 */
    public Element makePatientEnteredVitalSign( String elementName, Element patientIdentifier, int countPatientEnteredVitalSigns, int countObservations, boolean updateRecordXml )
    {

        Element patientEnteredVitalSigns = DocumentHelper.createElement( "patientEnteredVitalSigns" );
        for ( int i = 0; i < countPatientEnteredVitalSigns; i++ )
        {
             
            Element patientEnteredVitalSign = DocumentHelper.createElement( "patientEnteredVitalSign" );

            List<Element> vitalSignObservationEvents = makeVitals( countObservations, patientIdentifier, updateRecordXml );
            for ( Element vitalSignObservationEvent : vitalSignObservationEvents )
            {
                patientEnteredVitalSign.add( vitalSignObservationEvent );
            }

            patientEnteredVitalSign.addElement( "dataEnterer" ).addText( "DataEnterer9876" );
            String comment = "This is a patient entered vital sign comment.";
            if(updateRecordXml)
            {
                comment = "This is a patient entered vital sign UPDATED comment.";
            }
            patientEnteredVitalSign.addElement( "comments" ).addText( comment );
            patientEnteredVitalSigns.add( patientEnteredVitalSign );
            
        }

        return patientEnteredVitalSigns;

    }

    public Element makePatientEnteredVitalSign( String elementName, Element patientIdentifier, int countObservations, boolean updateRecordXml )
    {

        Element patientEnteredVitalSigns = DocumentHelper.createElement( "patientEnteredVitalSigns" );
        Element patientEnteredVitalSign = DocumentHelper.createElement( "patientEnteredVitalSign" );

        List<Element> vitalSignObservationEvents = makeVitals( countObservations, patientIdentifier, updateRecordXml );
        for ( Element vitalSignObservationEvent : vitalSignObservationEvents )
        {
            patientEnteredVitalSign.add( vitalSignObservationEvent );
        }

        patientEnteredVitalSign.addElement( "dataEnterer" ).addText( "DataEnterer9876" );
        String comment = "This is a patient entered vital sign comment.";
        if(updateRecordXml)
        {
            comment = "This is a patient entered vital sign UPDATED comment.";
        }
        patientEnteredVitalSign.addElement( "comments" ).addText( comment );
        patientEnteredVitalSigns.add( patientEnteredVitalSign );

        return patientEnteredVitalSigns;

    }


    public Element makePatientEnteredVitalSign( String elementName, String recordIdentifier, String recordStatus )
    {

        Element patientEnteredVitalSigns = DocumentHelper.createElement( "patientEnteredVitalSigns" );
        Element patientEnteredVitalSign = DocumentHelper.createElement( "patientEnteredVitalSign" );
        Element newVitalSignObservationEvent = DocumentHelper.createElement( "vitalSignObservationEvent" );
        Element newRecordIdentifier = createHL72EntityIdentifier( "recordIdentifier", recordIdentifier );
        newVitalSignObservationEvent.add( newRecordIdentifier );

        patientEnteredVitalSign.add( newVitalSignObservationEvent );
        patientEnteredVitalSign.addElement( "recordStatus" ).addText( recordStatus );
        patientEnteredVitalSigns.add( patientEnteredVitalSign );

        return patientEnteredVitalSigns;

    }


    public void printVitals( List<Element> listOfResults )
    {
        printDomainRecords( listOfResults );
    }


    public void printVitals( List<Element> listOfResults, Logger aLogger )
    {
        printDomainRecords( listOfResults, aLogger );
    }


    protected void printVital( Element vital )
    {
        printDomainRecord( vital );
    }


    protected void printVital( Element vital, Logger aLogger )
    {
        printDomainRecord( vital, aLogger );
    }


    public String fillPrintBuffer( Object object )
    {
        String returnString = "";

        if ( ( object != null ) && ( object instanceof Element ) )
        {
            returnString = ( ( Element )object ).asXML();
        }

        return returnString;
    }


    /*
    <xsd:complexType name="HomeTelehealthMonitor">
    <xsd:sequence>
      <xsd:element minOccurs="0" name="vendor" type="xsd:string"/>
      <xsd:element minOccurs="0" name="homeAppliance" type="xsd:string"/>
      <xsd:element minOccurs="0" name="measurementDevice" type="xsd:string"/>
    </xsd:sequence>
    </xsd:complexType>
     */
    private Element makeHomeTelehealthMonitor( String elementName, boolean updateRecordXml )
    {
        Element newHomeTelehealthMonitor = DocumentHelper.createElement( elementName );

        newHomeTelehealthMonitor.addElement( "vendor" ).addText( "UpdatedVendor" );
        newHomeTelehealthMonitor.addElement( "homeAppliance" ).addText( "UpdatedHomeAppliance" );
        newHomeTelehealthMonitor.addElement( "measurementDevice" ).addText( "UpdatedMeasurementDevice" );

        return newHomeTelehealthMonitor;
    }


    private Element makeHomeTelehealthMonitor( String elementName )
    {
        Element newHomeTelehealthMonitor = DocumentHelper.createElement( elementName );

        newHomeTelehealthMonitor.addElement( "vendor" ).addText( "Vendor" );
        newHomeTelehealthMonitor.addElement( "homeAppliance" ).addText( "HomeAppliance" );
        newHomeTelehealthMonitor.addElement( "measurementDevice" ).addText( "MeasurementDevice" );

        return newHomeTelehealthMonitor;
    }


    /*
    <xsd:complexType name="OxygenAdministration">
    <xsd:sequence>
      <xsd:element minOccurs="0" name="flowRateValue" type="xsd:string"/>
      <xsd:element minOccurs="0" name="flowRateUnit" type="basedatatypes:HL72CodedElementLite"/>
      <xsd:element minOccurs="0" name="concentrationValue" type="xsd:string"/>
      <xsd:element minOccurs="0" name="concentrationUnit" type="basedatatypes:HL72CodedElementLite"/>
    </xsd:sequence>
    </xsd:complexType>
     */
    private Element makeOxygenAdministration( String elementName )
    {
        Element newOxygenAdministration = DocumentHelper.createElement( elementName );

        newOxygenAdministration.addElement( "flowRateValue" ).addText( "FlowRateValue" );

        Element newFlowRateUnit = createHL72CodedElementLite( "flowRateUnit", "VistaFlowRateUnit", "FlowRateUnit 1" );
        newOxygenAdministration.add( newFlowRateUnit );

        newOxygenAdministration.addElement( "concentrationValue" ).addText( "ConcentrationValue" );

        Element newConcentrationUnit = createHL72CodedElementLite( "concentrationUnit", "VistaConcentrationUnit", "ConcentrationUnit 1" );
        newOxygenAdministration.add( newConcentrationUnit );

        return newOxygenAdministration;
    }


    /*
    <xsd:complexType name="VitalSignObservation">
    <xsd:sequence>
      <xsd:element minOccurs="0" name="value" type="xsd:string"/>
      <xsd:element minOccurs="0" name="unit" type="basedatatypes:HL72CodedElementLite"/>
      <xsd:element maxOccurs="unbounded" minOccurs="0" name="qualifier" type="vitalsigns:VitalSignQualifier"/>
    </xsd:sequence>
    </xsd:complexType>
     */
    /*sample xml ...
     * <vitalSignObservation>
        <value>value</value>
        <unit>
          <code>code</code>
          <displayText>displayText</displayText>
          <codingSystem>codingSystem</codingSystem>
        </unit>
        <qualifier>
          <value>
            <code>code</code>
            <displayText>displayText</displayText>
            <codingSystem>codingSystem</codingSystem>
          </value>
        </qualifier>
      </vitalSignObservation>
     */
    private Element makeVitalSignObservation( String elementName )
    {
        Element newVitalSignObservation = DocumentHelper.createElement( elementName );
        
        newVitalSignObservation.addElement( "value" ).addText( "Value" );

        Element newUnit = createHL72CodedElementLite( "unit", "Unit" );
        newVitalSignObservation.add( newUnit );

        newVitalSignObservation.addElement( "internationalValue" ).addText( "InternationalValue" );

        Element newInternationalUnit = createHL72CodedElementLite( "internationalUnit", "InternationalUnit" );
        newVitalSignObservation.add( newInternationalUnit );

        Element vitalSignQualifiers = DocumentHelper.createElement( "qualifiers" );
        Element vitalSignQualifier1 = DocumentHelper.createElement( "qualifier" );

        //int index = this.recordIdentifierIdentity == null ? 0 : 1;//create use 0 index, update overwrites creates and adds a new one
        int index = 0;
        Element newVitalSignQualifierValue1 = createHL72CodedElementLite( "value", QUALIFIERS, index );
        vitalSignQualifier1.add( newVitalSignQualifierValue1 );
        vitalSignQualifiers.add( vitalSignQualifier1 );
       
        //index++;
        index = this.recordIdentifierIdentity == null ? 0 : 1;//create use 0 index, update overwrites creates and adds a new one
        if(index == 1){
           
            Element vitalSignQualifier2 = DocumentHelper.createElement( "qualifier" );
            
            Element newVitalSignQualifierValue2 = createHL72CodedElementLite( "value", QUALIFIERS, index );
            vitalSignQualifier2.add( newVitalSignQualifierValue2 );
            vitalSignQualifiers.add( vitalSignQualifier2 );
        }
                
        newVitalSignObservation.add( vitalSignQualifiers );

        return newVitalSignObservation;
    }

}
