package gov.va.med.esr.messaging.parser;

import gov.va.med.esr.common.infra.ImpreciseDate;
import gov.va.med.esr.common.model.ee.IncompetenceRuling;
import gov.va.med.esr.common.model.ee.MedicaidFactor;
import gov.va.med.esr.common.model.ee.MilitaryService;
import gov.va.med.esr.common.model.ee.MilitaryServiceSiteRecord;
import gov.va.med.esr.common.model.lookup.DeathDataSource;
import gov.va.med.esr.common.model.lookup.SSNType;
import gov.va.med.esr.common.model.person.DeathRecord;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.model.person.SSN;
import gov.va.med.esr.messaging.builder.message.DateFormatter;
import gov.va.med.fw.service.ServiceException;
import gov.va.med.fw.util.builder.BuilderException;

import java.util.Date;
import java.util.Iterator;
import java.util.Set;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

/**
 * 
 * @author Rajiv Patnaik Created on Aug 5, 2005
 * @version 1.0
 * 
 * Copyright © 2005 VHA. All rights reserved
 */
public class ZPDTestDataValidator extends BaseSegmentsTestDataValidator
        implements XMLSegmentTagNameConstants
{

    /**
     * @param person
     * @param pidNode
     * @throws ServiceException
     */
    public void validateZPD(Document document, Person person) throws Exception
    {
        String sendingFacilityStationNumber = getSendingFacilityStationNumber(document);

        NodeList zpdNodes = document.getElementsByTagName(ZPD);

        for (int i = 0; i < zpdNodes.getLength(); i++)
        {
            Element element = (Element) zpdNodes.item(i);

            //Rated Incompetent
            validateRatedIncompetent(person, element);

            //Active Health Insurance
            //Eligible for Medicaid. Date medicaid last asked
            validateMedicaid(person, element);

            //POW Status Indicated -ZPD.getPowStatusIndicated()...
            //Doesn't look like anyone is using it

            //Medication Copay exempt status

            //Dateof death, Source of death notifictn.Datetime of death
            validateDeathRecord(person, element);

            //Filipino veteran Proof
            validateFilipinoVeteranProof(person, sendingFacilityStationNumber,
                    element);
            
            validateVeteranPseudoSSNReason(person, element);         

        }

    }

    /**
     * @param person
     * @param sendingFacilityStationNumber
     * @param element
     */
    private void validateFilipinoVeteranProof(Person person,
            String sendingFacilityStationNumber, Element element)
    {
        String filipinoVeteranProofFromMsg = getElement(element, ZPD_33);
        MilitaryService militaryService = person
        	.getMilitaryService();
        
        if (filipinoVeteranProofFromMsg != null)
        {
            assertNotNull("MilitaryService is null", militaryService);

            MilitaryServiceSiteRecord siteRecord = person.getMilitaryService()
                    .getMilitaryServiceSiteRecordsBySite(
                            sendingFacilityStationNumber);
            assertNotNull("siteRecord is null", siteRecord);
            assertNotNull("FilipinoVeteranProof is null", siteRecord
                    .getFilipinoVeteranProof());
            assertEquals("FilipinoVeteranProof is not equal",
                    filipinoVeteranProofFromMsg, siteRecord
                            .getFilipinoVeteranProof().getCode());
        }
    }

    /**
     * @param person
     * @param element
     * @throws BuilderException
     * @throws ServiceException
     */
    private void validateRatedIncompetent(Person person, Element element)
    {
        /*RP TODO With new rated Incompetent rules from PAt
        String ratedIncompetent = getElement(element, ZPD_8);
        IncompetenceRuling incompetenceRuling = person.getIncompetenceRuling();
        validateNotNull(ratedIncompetent, person.getIncompetenceRuling(),
                "IncompetenceRuling is null");

        if (incompetenceRuling != null)
        {
            Boolean isIncompetent = incompetenceRuling
                    .isIncompetent();
            if(ratedIncompetent != null)
            {
                assertNotNull("isIncompetent is null", isIncompetent);
                assertEquals("Rated incompetent not equal", buildBoolean(
                        ratedIncompetent).booleanValue(), isIncompetent
                        .booleanValue());
                
            }
        }*/
    }

    private void validateMedicaid(Person person, Element element)
    {
        //Eligible for Medicaid
        String medicaidEligibleFromMsg = getElement(element, ZPD_12);
        //Date medicaid last asked
        String dateMedicaidLastAskedFromMsg = getSubElementData(element,
                ZPD_13, TS_1);

        MedicaidFactor medicaidFactor = person.getMedicaidFactor();

        validateNotNull(medicaidEligibleFromMsg, medicaidFactor,
                "MedicaidFactor is null");

        if (medicaidFactor != null)
        {
            Boolean isEligibleForMedicaid = medicaidFactor
                    .isEligibleForMedicaid();
            assertEquals("EligibleForMedicaid does not match", buildBoolean(
                    medicaidEligibleFromMsg).booleanValue(),
                    isEligibleForMedicaid.booleanValue());

            Date dateMedicaidLastAsked = medicaidFactor.getLastUpdateDate();
            //TODO ..fails
            //assertEquals("dateMedicaidLastAsked does not match",
            //      dateMedicaidLastAskedFromMsg, DateFormatter
            //            .formatDate(dateMedicaidLastAsked));
        }
    }

    private void validateDeathRecord(Person person, Element element)
    {
        String dateOfdeathFromMsg = getSubElementData(element, ZPD_9, TS_1);
       
        String sourceOfDeathFromMsg = getElement(element, ZPD_31);
        //Date medicaid last asked
        String dateTimeOfDeathNotificationFromMsg = getSubElementData(element, ZPD_32, TS_1);

        DeathRecord deathRecord = person.getDeathRecord();
        validateNotNull(sourceOfDeathFromMsg, deathRecord,
                "DeathRecord is null");

        if (deathRecord != null)
        {
            ImpreciseDate dateOfDeath = deathRecord.getDeathDate();
            String dateofDeathStr = DateFormatter.formatDate(dateOfDeath);
            assertEquals("DeathDate does not match", dateOfdeathFromMsg,
                    dateofDeathStr);
            
            DeathDataSource sourceOfDeath = deathRecord.getDataSource();
            //assertEquals("", sourceOfDeathFromMsg, sourceOfDeath.getCode());

            ImpreciseDate dateOfDeathNotification = deathRecord.getDeathDate();
            String dateofDeathNotificationStr = DateFormatter.formatDate(dateOfDeathNotification);
            assertEquals("DeathDate does not match", dateTimeOfDeathNotificationFromMsg,
                    dateofDeathNotificationStr);
        }
    }

    private void validateVeteranPseudoSSNReason(Person person, Element element)
    {
        //Eligible for Medicaid
        String ssnReasonFromMsg = getElement(element, ZPD_34);

        Set ssns = person.getSsns();

        if (ssnReasonFromMsg != null)
        {
            //If a reason exists, there has to be a SSN for the person
            assertNotNull("Sssn in Person is null", ssns);

            SSN pseudoSSN = SSN.getSSNOfType(ssns, SSNType.CODE_ACTIVE.getName());
            
            assertNotNull("pseudoSSN is null",  pseudoSSN);
            assertEquals("SSN type does not match", ssnReasonFromMsg, pseudoSSN
                    .getPseudoSSNReason());
        }

    }
}