

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


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

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


public class TiuBuilder
    extends
        AbstractEntryPointBuilder
{
    public static final String[] DATA_ENTERERS = { "data_enterer_1", "data_enterer_2", "data_enterer_3" };
    public static final String[] AUTHORS = { "author_11", "author_12", "author_13" };
    public static final String[] SIGNERS = { "signer_21", "signer_22", "signer_23", "signer_24", "signer_25", "signer_26" };
    public static final String[] COSIGNERS = { "cosigner_31", "cosigner_32", "cosigner_33", "cosigner_34", "cosigner_35", "cosigner_36" };
    public static final String[] CLOSERS = { "closer_41", "closer_42", "closer_43" };
    public static final String[] AMENDERS = { "amender_51", "amender_52", "amender_53" };
    public static final String[] REASSIGNERS = { "reassigner_61", "reassigner_62", "reassigner_63" };
    public static final String[] EDITORS = { "editor_71", "editor_72", "editor_73" };
    public static final String[] MARKERS = { "marker_81", "marker_82", "marker_83" };
    public static final String[] RETRACTORS = { "retractor_91", "retractor_92", "retractor_93" };
    public static final String[] ATTENDINGS = { "attending_101", "attending_102", "attending_103" };
    public static final String[] DELETERS = { "deleter_111", "deleter_112", "deleter_113" };
    protected static Log logger = null;
    private static final String RECORD_VERSION = "12345";

    private int TIU_IDX = 60000;


    public TiuBuilder( )
    {
        super();
    }


    public TiuBuilder( Random aRandom )
    {
        super( aRandom );
    }


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

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

        return returnString;
    }


    @Override
    public Element createEntryPointRecord( Element personIdentifier )
    {
        return makeClinicalDocumentEvent( personIdentifier );
    }


    public Element makeClinicalDocumentEvent( )
    {
        return makeClinicalDocumentEvent( null );
    }


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


    public Element makeClinicalDocumentEvent( Element patient )
    {
        Element newClinicalDocumentEvent = createClinicalDocumentEvent( TIU_IDX++ , patient );

        return newClinicalDocumentEvent;
    }


    public List<Element> makeClinicalDocumentEvents( int number, Element patient )
    {
        List<Element> newClinicalDocumentEvents = new ArrayList<Element>( number );
        for ( int i = 0; i < number; i++ )
        {
            newClinicalDocumentEvents.add( makeClinicalDocumentEvent( patient ) );
        }

        return newClinicalDocumentEvents;
    }


    /*
    <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
    <!--  ClinicalDocumentEvent  -->
    <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
    <xsd:complexType name="ClinicalDocumentEvent">
    <xsd:sequence>
      <xsd:element name="recordIdentifier" type="basedatatypes:HL72EntityIdentifier"/>
      <xsd:element name="patient" type="common:PatientLite"/>
      <xsd:element name="referenceDate" type="basedatatypes:PointInTime"/>
      <xsd:element minOccurs="0" name="parentIdentifier" type="basedatatypes:HL72EntityIdentifier"/>
      <xsd:element minOccurs="0" name="standardizedDocumentTitle" type="xsd:string"/>
      <xsd:element minOccurs="0" name="documentTitle" type="xsd:string"/>
      <xsd:element minOccurs="0" name="documentSubject" type="xsd:string"/>
      <xsd:element maxOccurs="unbounded" minOccurs="0" name="documentText" type="xsd:string"/>
      <xsd:element minOccurs="0" name="documentContent" type="xsd:string"/>
      <xsd:element minOccurs="0" name="statusCode" type="basedatatypes:HL72CodedElementLite"/>
      <xsd:element minOccurs="0" name="dataEnterer" type="common:PractitionerParticipationLite"/>
      <xsd:element minOccurs="0" name="author" type="common:PractitionerParticipationLite"/>
      <xsd:element minOccurs="0" name="chartMarkedSigned" type="common:PractitionerLite"/>
      <xsd:element minOccurs="0" name="chartMarkedCosigned" type="common:PractitionerLite"/>
      <xsd:element minOccurs="0" name="expectedSigner" type="tiu:ManagedPractitionerParticipationLite"/>
      <xsd:element minOccurs="0" name="signer" type="tiu:ManagedPractitionerParticipationLite"/>
      <xsd:element minOccurs="0" name="expectedCosigner" type="tiu:ManagedPractitionerParticipationLite"/>
      <xsd:element minOccurs="0" name="cosigner" type="tiu:ManagedPractitionerParticipationLite"/>
      <xsd:element maxOccurs="unbounded" minOccurs="0" name="otherExpectedCosigners" type="tiu:ManagedPractitionerParticipationLite"/>
      <xsd:element maxOccurs="unbounded" minOccurs="0" name="otherCosigners" type="tiu:ManagedPractitionerParticipationLite"/>
      <xsd:element minOccurs="0" name="adminCloser" type="tiu:ManagedPractitionerParticipationLite"/>
      <xsd:element minOccurs="0" name="amender" type="tiu:ManagedPractitionerParticipationLite"/>
      <xsd:element minOccurs="0" name="amendmentDate" type="basedatatypes:PointInTime"/>
      <xsd:element minOccurs="0" name="dictationDate" type="basedatatypes:PointInTime"/>
      <xsd:element minOccurs="0" name="patientMovementDate" type="basedatatypes:PointInTime"/>
      <xsd:element minOccurs="0" name="archiveDate" type="basedatatypes:PointInTime"/>
      <xsd:element minOccurs="0" name="procedureDate" type="basedatatypes:PointInTime"/>
      <xsd:element minOccurs="0" name="procedureSummaryCode" type="basedatatypes:HL72CodedElementLite"/>
      <xsd:element minOccurs="0" name="treatingSpecialtyCode" type="basedatatypes:HL72CodedElementLite"/>
      <xsd:element minOccurs="0" name="serviceCode" type="basedatatypes:HL72CodedElementLite"/>
      <xsd:element minOccurs="0" name="cosignatureNeeded" type="basedatatypes:HL72CodedElementLite"/>
      <xsd:element maxOccurs="unbounded" minOccurs="0" name="documentUpdateEvents" type="tiu:DocumentUpdateEvent"/>
      <xsd:element minOccurs="0" name="treatmentEpisode" type="tiu:TreatmentEpisode"/>
      <xsd:element minOccurs="0" name="patientVisit" type="tiu:TiuPatientVisit"/>
      <xsd:element minOccurs="0" name="retraction" type="tiu:RetractionEvent"/>
      <xsd:element maxOccurs="unbounded" minOccurs="0" name="images" type="tiu:Image"/>
      <xsd:element name="recordVersion" type="xsd:int"/>
      <xsd:element name="recordUpdateTime" type="basedatatypes:PointInTime"/>
    </xsd:sequence>
    </xsd:complexType>
     */
    private Element createClinicalDocumentEvent( int id, Element patient )
    {
        Element element = DocumentHelper.createElement( "clinicalDocumentEvents" );

        element.add( createHL72EntityIdentifier( "recordIdentifier", id ) );

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

        element.add( createFixedPointInTime( "referenceDate" ) );
        element.add( createHL72EntityIdentifier( "parentIdentifier" ) );
        element.add( createHL72CodedElementLite( "standardizedDocumentTitle", "StandardizedDocumentTitle" ) );
        element.addElement( "documentTitle" ).setText( "DocumentTitle" );
        element.addElement( "documentSubject" ).setText( "DocumentSubject" );
        element.addElement( "documentText" ).setText( "DocumentText_1" );
        element.addElement( "documentText" ).setText( "DocumentText_2" );
        element.addElement( "documentContent" ).setText( "DocumentContent" );
        element.add( createHL72CodedElementLite( "statusCode", "StatusCode" ) );
        element.add( createPractitionerLite( "dataEnterer", DATA_ENTERERS ) );
        element.add( createPractitionerLite( "author", AUTHORS ) );
        element.add( createPractitionerLite( "chartMarkedSigned", SIGNERS ) );
        element.add( createPractitionerLite( "chartMarkedCosigned", COSIGNERS ) );
        element.add( createPractitionerLite( "expectedSigner", SIGNERS ) );
        element.add( createManagedPractitionerParticipationLite( "signer", SIGNERS ) );
        element.add( createPractitionerLite( "expectedCosigner", COSIGNERS ) );
        element.add( createManagedPractitionerParticipationLite( "cosigner", COSIGNERS ) );
        element.add( createPractitionerLite( "otherExpectedCosigners", COSIGNERS ) );
        element.add( createPractitionerLite( "otherExpectedCosigners", COSIGNERS ) );
        element.add( createManagedPractitionerParticipationLite( "otherCosigners", COSIGNERS ) );
        element.add( createManagedPractitionerParticipationLite( "otherCosigners", COSIGNERS ) );
        element.add( createManagedPractitionerParticipationLite( "adminCloser", CLOSERS ) );
        element.add( createManagedPractitionerParticipationLite( "amender", AMENDERS ) );
        element.add( createFixedPointInTime( "amendmentDate" ) );
        element.add( createFixedPointInTime( "dictationDate" ) );
        element.add( createFixedPointInTime( "patientMovementDate" ) );
        element.add( createFixedPointInTime( "archiveDate" ) );
        element.add( createFixedPointInTime( "procedureDate" ) );
        element.add( createFixedPointInTime( "enteredDate" ) );
        element.add( createHL72CodedElementLite( "procedureSummaryCode", "ProcedureSummaryCode" ) );
        element.add( createHL72CodedElementLite( "treatingSpecialtyCode", "TreatingSpecialtyCode" ) );
        element.add( createHL72CodedElementLite( "serviceCode", "ServiceCode" ) );
        element.add( createHL72CodedElementLite( "cosignatureNeeded", "CosignatureNeeded" ) );
        element.add( createDocumentUpdateEvent( "documentUpdateEvents" ) );
        element.add( createTreatmentEpisode( "treatmentEpisode" ) );
        element.add( createTiuPatientVisit( "patientVisit" ) );
        element.add( createRetractionEvent( "retraction" ) );
        element.add( createImage( "images" ) );
        element.add( createImage( "images" ) );
        element.addElement( "recordVersion" ).setText( RECORD_VERSION );
        element.add( createFixedPointInTime( "recordUpdateTime" ) );

        return element;
    }


    /*
    <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
    <!--  Image  -->
    <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
    <xsd:complexType name="Image">
    <xsd:sequence>
      <xsd:element minOccurs="0" name="imageLinkCode" type="basedatatypes:HL72CodedElementLite"/>
    </xsd:sequence>
    </xsd:complexType>
     */
    private Element createImage( String elementName )
    {
        Element element = DocumentHelper.createElement( elementName );

        element.add( createHL72CodedElementLite( "imageLinkCode", "ImageLinkCode" ) );

        return element;
    }


    /*
    <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
    <!--  RetractionEvent  -->
    <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
    <xsd:complexType name="RetractionEvent">
    <xsd:sequence>
      <xsd:element minOccurs="0" name="retractor" type="common:PractitionerLite"/>
      <xsd:element minOccurs="0" name="reasonCode" type="basedatatypes:HL72CodedElementLite"/>
      <xsd:element minOccurs="0" name="retractionDate" type="basedatatypes:PointInTime"/>
      <xsd:element minOccurs="0" name="retractedOriginal" type="basedatatypes:HL72EntityIdentifier"/>
    </xsd:sequence>
    </xsd:complexType>
     */
    private Element createRetractionEvent( String elementName )
    {
        Element element = DocumentHelper.createElement( elementName );

        element.add( createPractitionerLite( "retractor", RETRACTORS ) );
        element.add( createHL72CodedElementLite( "reasonCode", "ReasonCode" ) );
        element.add( createFixedPointInTime( "retractionDate" ) );
        element.add( createHL72EntityIdentifier( "retractedOriginal" ) );

        return element;
    }


    /*
    <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
    <!--  TiuPatientVisit  -->
    <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
    <xsd:complexType name="TiuPatientVisit">
    <xsd:sequence>
      <xsd:element minOccurs="0" name="patientClass" type="xsd:string"/>
      <xsd:element minOccurs="0" name="assignedLocation" type="basedatatypes:HL72LocationIdentifier"/>
      <xsd:element minOccurs="0" name="attendingPhysician" type="common:PractitionerLite"/>
      <xsd:element minOccurs="0" name="hospitalService" type="xsd:string"/>
      <xsd:element minOccurs="0" name="serviceLocation" type="basedatatypes:HL72LocationIdentifier"/>
      <xsd:element minOccurs="0" name="visitDate" type="basedatatypes:PointInTime"/>
      <xsd:element minOccurs="0" name="servicingFacility" type="xsd:string"/>
      <xsd:element minOccurs="0" name="admitDate" type="basedatatypes:PointInTime"/>
      <xsd:element minOccurs="0" name="visitId" type="xsd:string"/>
      <xsd:element minOccurs="0" name="secondaryVisitDate" type="basedatatypes:PointInTime"/>
    </xsd:sequence>
    </xsd:complexType>
     */
    private Element createTiuPatientVisit( String elementName )
    {
        Element element = DocumentHelper.createElement( elementName );

        element.addElement( "patientClass" ).addText( "PatientClass" );
        element.add( createHL72LocationIdentifier( "assignedLocation", "AssignedLocation" ) );
        element.add( createPractitionerLite( "attendingPhysician", ATTENDINGS ) );
        element.addElement( "hospitalService" ).addText( "HospitalService" );
        element.add( createHL72LocationIdentifier( "serviceLocation", "ServiceLocation" ) );
        element.add( createPointInTime( "visitDate" ) );
        element.addElement( "servicingFacility" ).addText( "ServicingFacility" );
        element.add( createPointInTime( "admitDate" ) );
        element.addElement( "visitId" ).addText( "VisitId" );
        element.add( createPointInTime( "secondaryVisitDate" ) );

        return element;
    }


    /*
    <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
    <!--  TreatmentEpisode  -->
    <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
    <xsd:complexType name="TreatmentEpisode">
    <xsd:sequence>
      <xsd:element minOccurs="0" name="episodeBeginDate" type="basedatatypes:PointInTime"/>
      <xsd:element minOccurs="0" name="episodeEndDate" type="basedatatypes:PointInTime"/>
    </xsd:sequence>
    </xsd:complexType>
     */
    private Element createTreatmentEpisode( String elementName )
    {
        Element element = DocumentHelper.createElement( elementName );

        element.add( createPointInTime( "episodeBeginDate" ) );
        element.add( createPointInTime( "episodeEndDate" ) );

        return element;
    }


    /*
    <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
    <!--  DocumentUpdateEvent  -->
    <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
    <xsd:complexType name="DocumentUpdateEvent">
    <xsd:sequence>
      <xsd:element minOccurs="0" name="initialPatientName" type="basedatatypes:HL72PersonName"/>
      <xsd:element minOccurs="0" name="finalPatientName" type="basedatatypes:HL72PersonName"/>
      <xsd:element minOccurs="0" name="initialVisitDate" type="basedatatypes:PointInTime"/>
      <xsd:element minOccurs="0" name="finalVisitDate" type="basedatatypes:PointInTime"/>
      <xsd:element minOccurs="0" name="initialVisitLocation" type="basedatatypes:HL72LocationIdentifier"/>
      <xsd:element minOccurs="0" name="finalVisitLocation" type="basedatatypes:HL72LocationIdentifier"/>
      <xsd:element minOccurs="0" name="initialVisitType" type="basedatatypes:HL72CodedElementLite"/>
      <xsd:element minOccurs="0" name="finalVisitType" type="basedatatypes:HL72CodedElementLite"/>
      <xsd:element minOccurs="0" name="initialVisitRecord" type="xsd:string"/>
      <xsd:element minOccurs="0" name="finalVisitRecord" type="xsd:string"/>
      <xsd:element minOccurs="0" name="reassignmentDate" type="basedatatypes:PointInTime"/>
      <xsd:element minOccurs="0" name="reassigner" type="common:PractitionerLite"/>
      <xsd:element minOccurs="0" name="editDate" type="basedatatypes:PointInTime"/>
      <xsd:element minOccurs="0" name="editor" type="common:PractitionerLite"/>
      <xsd:element minOccurs="0" name="interdisciplinaryNoteParent" type="xsd:string"/>
      <xsd:element minOccurs="0" name="interdisciplinaryNoteMarker" type="common:PractitionerLite"/>
      <xsd:element minOccurs="0" name="interdisciplinaryNoteActionCode" type="basedatatypes:HL72CodedElementLite"/>
      <xsd:element minOccurs="0" name="interdisciplinaryNoteActionDate" type="basedatatypes:PointInTime"/>
      <xsd:element minOccurs="0" name="interdisciplinaryNoteEntryStatus" type="xsd:string"/>
      <xsd:element minOccurs="0" name="deleter" type="common:PractitionerLite"/>
      <xsd:element minOccurs="0" name="deletionDate" type="basedatatypes:PointInTime"/>
      <xsd:element minOccurs="0" name="deletionReasonCode" type="basedatatypes:HL72CodedElementLite"/>
    </xsd:sequence>
    </xsd:complexType>
     */
    private Element createDocumentUpdateEvent( String elementName )
    {
        Element element = DocumentHelper.createElement( elementName );

        element.add( createHL72PersonName( "initialPatientName" ) );
        element.add( createHL72PersonName( "finalPatientName" ) );
        element.add( createPointInTime( "initialVisitDate" ) );
        element.add( createPointInTime( "finalVisitDate" ) );
        element.add( createHL72LocationIdentifier( "initialVisitLocation", "InitialVisitLocation" ) );
        element.add( createHL72LocationIdentifier( "finalVisitLocation", "FinalVisitLocation" ) );
        element.add( createHL72CodedElementLite( "initialVisitType", "InitialVisitType" ) );
        element.add( createHL72CodedElementLite( "finalVisitType", "FinalVisitType" ) );
        element.addElement( "initialVisitRecord" ).addText( "InitialVisitRecord" );
        element.addElement( "finalVisitRecord" ).addText( "FinalVisitRecord" );
        element.add( createPointInTime( "reassignmentDate" ) );
        element.add( createPractitionerLite( "reassigner", REASSIGNERS ) );
        element.add( createPointInTime( "editDate" ) );
        element.add( createPractitionerLite( "editor", EDITORS ) );
        element.addElement( "interdisciplinaryNoteParent" ).addText( "InterdisciplinaryNoteParent" );
        element.add( createPractitionerLite( "interdisciplinaryNoteMarker", MARKERS ) );
        element.add( createHL72CodedElementLite( "interdisciplinaryNoteActionCode", "InterdisciplinaryNoteActionCode" ) );
        element.add( createPointInTime( "interdisciplinaryNoteActionDate" ) );
        element.addElement( "interdisciplinaryNoteEntryStatus" ).addText( "InterdisciplinaryNoteEntryStatus" );
        element.add( createPractitionerLite( "deleter", DELETERS ) );
        element.add( createPointInTime( "deletionDate" ) );
        element.add( createHL72CodedElementLite( "deletionReasonCode", "DeletionReasonCode" ) );

        return element;
    }


    /*
    <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
    <!--  ManagedPractitionerParticipationLite  -->
    <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
    <xsd:complexType name="ManagedPractitionerParticipationLite">
    <xsd:sequence>
      <xsd:element minOccurs="0" name="practitioner" type="common:PractitionerLite"/>
      <xsd:element minOccurs="0" name="participationType" type="xsd:string"/>
      <xsd:element minOccurs="0" name="participationDate" type="basedatatypes:PointInTime"/>
      <xsd:element minOccurs="0" name="signatureBlockName" type="xsd:string"/>
      <xsd:element minOccurs="0" name="signatureBlockTitle" type="xsd:string"/>
      <xsd:element minOccurs="0" name="signatureMode" type="basedatatypes:HL72CodedElementLite"/>
    </xsd:sequence>
    </xsd:complexType>
     */
    private Element createManagedPractitionerParticipationLite( String elementName, String[] sourcePersonIds )
    {
        Element practitionerLite = createPractitionerLite( "practitioner", sourcePersonIds );
        Element signatureMode = createHL72CodedElementLite( "signatureMode", "SignatureMode" );

        return CommonBuilder.createManagedPractitionerParticipationLite( elementName, practitionerLite, signatureMode );
    }
}
