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

import gov.va.med.esr.common.model.financials.IncomeTest;
import gov.va.med.esr.common.model.financials.IncomeTestStatus;
import gov.va.med.esr.common.model.lookup.IncomeTestType;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.messaging.builder.message.DateFormatter;
import gov.va.med.esr.service.PersonHelperService;

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 9, 2005
 * @version 1.0
 * 
 * Copyright © 2005 VHA. All rights reserved
 */
public class ZMTTestDataValidator extends BaseSegmentsTestDataValidator
        implements XMLSegmentTagNameConstants
{
    public void validateZMT(Document document, Person person,
            PersonHelperService personHelperService) throws Exception
    {
        IncomeTest incomeTest = personHelperService
                .getCurrentIncomeTest(person);

        NodeList nodeList = document.getElementsByTagName(ZMT);
        for (int i = 0; i < nodeList.getLength(); i++)
        {
            Element element = (Element) nodeList.item(i);
            String setId = getElement(element, ZMT_1);
            //1= Means Test, 2 = Co-pay Test, 4=LTC Co-pay Exemption Tes
            //The Z07 Test Data file contains the required info for
            //IncomeTest and IncomeTestStatus
            if (IncomeTestType.CODE_MEANS_TEST.getName().equals(setId))
            {
                validateIncomeTestData(person, element, personHelperService);
                validateMeansTestData(person, element,
                        IncomeTestType.CODE_MEANS_TEST.getName(), incomeTest);
            } else if (IncomeTestType.CODE_CO_PAY_EXEMPTION_TEST.getName()
                    .equals(setId))
            {
                validateMeansTestData(person, element,
                        IncomeTestType.CODE_CO_PAY_EXEMPTION_TEST.getName(),
                        incomeTest);
            } else if (IncomeTestType.CODE_LTC_CO_PAY_TEST.getName().equals(
                    setId))
            {
                validateMeansTestData(person, element,
                        IncomeTestType.CODE_LTC_CO_PAY_TEST.getName(),
                        incomeTest);
            }
        }
    }

    private void validateIncomeTestData(Person person, Element element,
            PersonHelperService personHelperService)
    {
        IncomeTest incomeTest = personHelperService
                .getCurrentIncomeTest(person);

        //EffectiveDate #2
        String effectiveDateFromMsg = getElement(element, ZMT_2);
        if (effectiveDateFromMsg != null)
        {
            assertNotNull("incomeTest is null", incomeTest);
            assertEquals("EffectiveDate does not match", effectiveDateFromMsg,
                    DateFormatter.formatDate(incomeTest.getEffectiveDate()));
        }

        //TotalIncome #4
        String totalIncomeFromMsg = getElement(element, ZMT_4);
        if (totalIncomeFromMsg != null)
        {
            assertNotNull("incomeTest is null", incomeTest);
            assertNotNull("TotalIncome is null", incomeTest.getTotalIncome());
            assertEquals("TotalIncome does not match", totalIncomeFromMsg,
                    incomeTest.getTotalIncome().toString());
        }

        String netWorthFromMsg = getElement(element, ZMT_5);
        if (netWorthFromMsg != null)
        {
            assertNotNull("incomeTest is null", incomeTest);
            assertNotNull("Net Worth is null", incomeTest.getNetWorth());
            assertEquals("Net Worth does not match", netWorthFromMsg,
                    incomeTest.getNetWorth().toString());

        }

        String adjudicationDateFromMsg = getElement(element, ZMT_6);

        String agreesToPayDeductibleFromMsg = getElement(element, ZMT_7);

        if (adjudicationDateFromMsg != null
                || agreesToPayDeductibleFromMsg != null)
        {
            assertNotNull("incomeTest is null", incomeTest);

            validateDate(incomeTest.getAdjudicationDate(),
                    adjudicationDateFromMsg, "AdjudicationDate is null",
                    "AdjudicationDate does not match");

            assertEquals("AgreesToPayDeductible does not match",
                    buildBoolean(agreesToPayDeductibleFromMsg), incomeTest
                            .getAgreesToPayDeductible());
        }

        /*
         * TODO Complete the rest
         * 
         * incomeTest.getThresholdA()//#8
         * incomeTest.getDeductibleExpenses()//Seq 9
         * incomeTest.getTotalNumberOfDependents()//#12
         * incomeTest.getIvmVerifiedMTCompletedDate//#20
         * incomeTest.getGMTThresholdAmount()//#28
         * incomeTest.getHardship().getReviewDate();//#23
         * incomeTest.getHardship().getEffectiveDate()//#24
         * incomeTest.getHardship().getReason()//#29
         * incomeTest.getSiteConductingTest()//#22
         */
    }

    private void validateMeansTestData(Person person, Element element,
            String incomeTestType, IncomeTest incomeTest)
    {
        String meansTestStatusFromMsg = getElement(element, ZMT_3);

        IncomeTestStatus incomeTestStatus = getIncomeTestStatus(person,
                incomeTestType, incomeTest);
        //validateNotNull(meansTestStatusFromMsg, incomeTestStatus,
        //"incomeTestStatus is null");

        if (incomeTestStatus != null)
        {
            assertLookupCode(incomeTestStatus.getStatus(),
                    meansTestStatusFromMsg,
                    "meansTestStatus code does not match");

            String completedDateFromMsg = getSubElementData(element, ZMT_10,
                    TS_1);
            validateDate(incomeTestStatus.getCompletedDate(),
                    completedDateFromMsg.substring(0, 8),
                    "CompletedDate is null", "CompletedDate does not match");

            String lastEditedDateFromMsg = getSubElementData(element, ZMT_25,
                    TS_1);
            validateDate(incomeTestStatus.getLastEditedDate(),
                    lastEditedDateFromMsg.substring(0, 8),
                    "LastEditedDate is null", "LastEditedDate does not match");

            String determinedStatusFromMsg = getElement(element, ZMT_26);
            assertLookupCode(incomeTestStatus.getDeterminedStatus(),
                    determinedStatusFromMsg, "DeterminedStatus does not match");
        }

    }

    private IncomeTestStatus getIncomeTestStatus(Person person,
            String incomeTestStatusType, IncomeTest incomeTest)
    {
        IncomeTestStatus incomeTestStatus = null;
        if (incomeTest != null)
        {
            Set statuses = incomeTest.getStatuses();

            if (statuses != null)
            {
                Iterator iterStatuses = statuses.iterator();
                while (iterStatuses.hasNext())
                {
                    IncomeTestStatus theStatus = (IncomeTestStatus) iterStatuses
                            .next();
                    if ((theStatus != null) && (theStatus.getType() != null))
                    {
                        if (incomeTestStatusType.equals(theStatus.getType()
                                .getCode()))
                        {
                            incomeTestStatus = theStatus;
                            break;
                        }
                    }
                }
            }
        }
        return incomeTestStatus;

    }
}