package gov.va.med.esr.common.batchprocess;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import gov.va.med.esr.common.infra.ImpreciseDate;
import gov.va.med.esr.common.model.ee.CampLejeuneVerification;
import gov.va.med.esr.common.model.ee.CampLejeuneVerificationMethod;
import gov.va.med.esr.common.model.lookup.CampLejeuneChangeSource;
import gov.va.med.esr.common.model.lookup.CampLejeuneVerificationType;
import gov.va.med.esr.common.model.lookup.Indicator;
import gov.va.med.esr.common.model.lookup.NameType;
import gov.va.med.esr.common.model.lookup.SSNType;
import gov.va.med.esr.common.model.lookup.VAFacility;
import gov.va.med.esr.common.model.lookup.CampLejeuneVerificationType.Code;
import gov.va.med.esr.common.model.person.BirthRecord;
import gov.va.med.esr.common.model.person.Name;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.model.person.SSN;
//import gov.va.med.esr.common.persistent.hibernate.CampLejeuneVerificationMethod;
import gov.va.med.esr.service.LookupService;
import gov.va.med.esr.service.PersonIdentityTraits;

import gov.va.med.fw.batchprocess.CampLejeuneImportProcessStatistics;
import gov.va.med.fw.io.AbstractRawFileDataContainer;
import gov.va.med.fw.io.ClassMapping;
import gov.va.med.fw.io.RawFileDataContainerUtils;
import gov.va.med.fw.service.ServiceException;
import gov.va.med.fw.util.StringUtils;



import org.apache.commons.collections.OrderedMap;
import org.apache.commons.lang.builder.ToStringBuilder;

import com.infomata.data.DataRow;

/**
 * Data object from CLEAR Extract record
 * @author DNS   TSAIG
 *
 */
public class CampLejeuneImportData extends AbstractRawFileDataContainer {
	
/**
	 * 
	 */
	private static final long serialVersionUID = -8131081638932278722L;

	private static HashMap codeMap = new HashMap();
	private String firstName;
	private String lastName;
	private String ssn;
	private String dob;
	private String gender;
	
	private String cleIndicator;
	private String verifiedMethod;
	private String comments;
	private String clRegistrationDate;
	
	private String veteranIdentifiers = null;
	private String icn = ""; //avoid null pointer exception in getVeteranIdentifiers() if icn is null
	
	private PersonIdentityTraits traits = null;
	private CampLejeuneVerification clv = null;
	
	static {
		RawFileDataContainerUtils.autoRegisterConvertersForClass();
	}
	
	protected void buildToString(ToStringBuilder builder) {		
		builder.append("firstName", firstName);
		builder.append("lastName", lastName);
		builder.append("ssn", ssn);
		builder.append("dob", dob);
		builder.append("gender", gender);
		builder.append("cleIndicator", cleIndicator);
		builder.append("verifiedMethod", verifiedMethod);
		builder.append("comments", comments);
		builder.append("clRegistrationDate", clRegistrationDate);
		builder.append("icn", icn);
	}

    /* (non-Javadoc)
     * @see gov.va.med.fw.io.RawFileDataContainer#setRawFileData(java.lang.String, com.infomata.data.DataRow, gov.va.med.fw.io.ClassMapping)
     */
    public void setRawFileData(String rawFileData, DataRow parsedRow,
            ClassMapping classMapping) throws Exception
    {
 		lastName = StringUtils.stripToNull(parsedRow.getString(2));
 		firstName = StringUtils.stripToNull(parsedRow.getString(3));
 		ssn = StringUtils.stripToNull(parsedRow.getString(5));
		dob = StringUtils.stripToNull(parsedRow.getString(7));
 		gender = StringUtils.stripToNull(parsedRow.getString(8));
 		if((gender==null)|| gender.length()<1)
 		{
 			gender="M";
 		}
 		
 		clRegistrationDate = StringUtils.stripToNull(parsedRow.getString(16));
 		cleIndicator = StringUtils.stripToNull(parsedRow.getString(17));
 		verifiedMethod = StringUtils.stripToNull(parsedRow.getString(18));
 		comments = StringUtils.stripToNull(parsedRow.getString(25));

		//verify that all the required fields are specified
 		String errMsg = isDataValid();
		if (!StringUtils.isEmpty(errMsg)){
			throw new Exception("ERROR: Missing required data: " + errMsg);			
		}
		
    }
    
	public String getVeteranIdentifiers() {
		return new StringBuffer(icn).append(CampLejeuneImportProcessStatistics.DELIMITER).
			append(firstName).append(CampLejeuneImportProcessStatistics.DELIMITER).
			append(lastName).append(CampLejeuneImportProcessStatistics.DELIMITER).
			append(ssn).append(CampLejeuneImportProcessStatistics.DELIMITER).
			append(dob).append(CampLejeuneImportProcessStatistics.DELIMITER).
			append(gender).toString();
	}
	
    public PersonIdentityTraits getPersonTraits(LookupService lookupService) throws ServiceException{
    	if (traits == null) {
    		traits = new PersonIdentityTraits();
    		Name name = new Name();
    		name.setFamilyName(getLastName());
    		name.setGivenName(getFirstName());
    		name.setType(lookupService.getNameTypeByCode(NameType.LEGAL_NAME.getName()));
    		traits.addName(name);
    		
    		SSN ssn = new SSN();
    		ssn.setSsnText(getSsn()); //samples: “222222222”, “000000000”, “333333333”, “111111111”
    		ssn.setType(lookupService.getSSNTypeByCode(SSNType.CODE_ACTIVE.getName()));
    		traits.setSsn(ssn);
    		
    		BirthRecord birthRecord = new BirthRecord();
    		birthRecord.setBirthDate(new ImpreciseDate(getDob())); //samples:“19300813”, “1900”, “19480102”, “1920”
    		traits.setBirthRecord(birthRecord);
    		
    		if (getGender() != null) { //samples: “M”, “M”, “”, “M”
    			traits.setGender(lookupService.getGenderByCode(getGender()));
    		}
    	}
    	
    	return traits;
    }
    
    public CampLejeuneVerification getCampLejeuneVerification(LookupService lookupService) throws ServiceException {
    	
    	if (clv == null) {
    	       clv = new CampLejeuneVerification();
               if ("Yes".equalsIgnoreCase(cleIndicator)) { //samples: “Yes”, “Yes”, “”, “Yes”
                      clv.setSpecialFactorIndicator(lookupService.getIndicatorByCode(Indicator.YES));
               } else if ("No".equalsIgnoreCase(cleIndicator)) {
                      clv.setSpecialFactorIndicator(lookupService.getIndicatorByCode(Indicator.NO));
               } else {
                      clv.setSpecialFactorIndicator(null); //blank
               }
               //set the change source as CLEAR so that the ilog rules know it is from the CLEAR extract batch job
               clv.setChangeSource(lookupService.getCampLejeuneChangeSourceByCode(CampLejeuneChangeSource.CODE_CLEAR.getCode()));
        	   clv.setChangeSite(lookupService.getVaFacilityByCode(VAFacility.CODE_HEC.getCode()));
               
        
               if (!StringUtils.isEmpty(verifiedMethod)) {//samples: “DoD,NPRC,CDC,Other,”, ”USMC,Other,”, ””, “NPRC,DPRIS,Other,”
                      List<String> clvms = getCodes(Arrays.asList(verifiedMethod.split(",")));
	               for(String clvVMStr1: clvms)
	               {
	                      CampLejeuneVerificationType clvtype1 = (CampLejeuneVerificationType)lookupService.getByCode(CampLejeuneVerificationType.class, clvVMStr1);
	                      if(clv.getCampLejeuneMethodByType(clvtype1)==null)
	                      {
	                             //add incoming new method to the on file record
	                             CampLejeuneVerificationMethod clvm = new CampLejeuneVerificationMethod();
	                             clvm.setVerificationType(clvtype1);
	                             clv.addCampLejeuneVerificationMethod(clvm);
	                      }   
	               }
               }
               if (!StringUtils.isEmpty(comments))
                      clv.setComments(StringUtils.replace(comments, "^^^", "|")); //samples: “Comments on Other^^^Comments on Verified residency Other checked.”, “Testing comments^^^Test comments. Comments and 1-to-N comments.”, “”, “TEsting Comments^^^Comments second time.”
               
               //samples: “2012-12-18”, “2013-01-15”, “2014-06-16”, “2014-08-13” -? Hung said it will be changed to yyyyMMdd, but the code below will still work 
               if (!StringUtils.isEmpty(clRegistrationDate))
            	   clv.setRegistrationDate( new ImpreciseDate(StringUtils.replace(clRegistrationDate, "-", ""))); //required
               
         //clv.setVerificationType(clvtype); ???
        
        //CLEAR does not have VAFacility
//             VAFacility vafac = (VAFacility)this.getLookup(VAFacility.class, VAFacility. CODE_HEC.getName());
//             clv.setChangeSite(vafac);

    	}
    	
    	return clv;
    }
    
    //code use merge method:
    /*
           clv =(CampLejeuneVerification)person.getSpecialFactorByType(CampLejeuneVerification.class);

        	if(clv ==null)
        	{
        		clv = new CampLejeuneVerification();
        		person.addSpecialFactor(clv);
        		clv = (CampLejeuneVerification)person.getSpecialFactorByType(CampLejeuneVerification.class);//re-get clv from person 
        	}

    		if ("Yes".equals(cleIndicator)) { //samples: “Yes”, “Yes”, “”, “Yes”
    			clv.setSpecialFactorIndicator(lookupService.getIndicatorByCode(Indicator.YES));
    		} else if ("No".equals(cleIndicator)) {
    			clv.setSpecialFactorIndicator(lookupService.getIndicatorByCode(Indicator.NO));
    		} else {
    			clv.setSpecialFactorIndicator(null); //blank
    		}
    		//set the change source as CLEAR so that the ilog rules know it is from the CLEAR extract batch job
    		clv.setChangeSource(lookupService.getCampLejeuneChangeSourceByCode(CampLejeuneChangeSource.CODE_CLEAR.getCode()));
    		
    		if (!StringUtils.isEmpty(verifiedMethod)) {//samples: “DoD,NPRC,CDC,Other,”, ”USMC,Other,”, ””, “NPRC,DPRIS,Other,”
    			List<String> clvms = getCodes(Arrays.asList(verifiedMethod.split(",")));
    			
    	    	if(clv.getInternalCampLejeuneVerificationMethods()!=null)
    	    	{
    	    		for (Iterator iter = clv.getInternalCampLejeuneVerificationMethods().iterator(); iter.hasNext();) {
    	    			CampLejeuneVerificationMethod clm = (CampLejeuneVerificationMethod) iter.next();
    	    			
    	    			//remove on file methods that are not in the incoming methods
    	    			if(!clvms.contains(clm.getVerificationType().getCode()))
    	    			{
    	    				clm.setSpecialFactor(null);
    	    				iter.remove();
    	    			}
    	    		}
    	    	}

    	    	for(String clvVMStr1: clvms)
    	    	{
    	    		CampLejeuneVerificationType clvtype1 = (CampLejeuneVerificationType)lookupService.getByCode(CampLejeuneVerificationType.class, clvVMStr1);
    	    		if(clv.getCampLejeuneMethodByType(clvtype1)==null)
    	    		{
    	    			//add incoming new method to the on file record
    	    			CampLejeuneVerificationMethod clvm = new CampLejeuneVerificationMethod();
    	    			clvm.setVerificationType(clvtype1);
    	    			clv.addCampLejeuneVerificationMethod(clvm);
    	    		}   
    	    	}
    		} else {
    			//no incoming clv method, wipe out on file methods if any
	    		for (Iterator iter = clv.getInternalCampLejeuneVerificationMethods().iterator(); iter.hasNext();) {
	    			CampLejeuneVerificationMethod clm = (CampLejeuneVerificationMethod) iter.next();
	    			clm.setSpecialFactor(null);
	    			iter.remove();
	    		}
    		}

    		if (!StringUtils.isEmpty(comments))
    			clv.setComments(StringUtils.replace(comments, "^^^", "|")); //samples: “Comments on Other^^^Comments on Verified residency Other checked.”, “Testing comments^^^Test comments. Comments and 1-to-N comments.”, “”, “TEsting Comments^^^Comments second time.”
    		
    		//samples: “2012-12-18”, “2013-01-15”, “2014-06-16”, “2014-08-13” -? Hung said it will be changed to yyyyMMdd, but the code below will still work 
    		clv.setRegistrationDate( new ImpreciseDate(StringUtils.replace(clRegistrationDate, "-", ""))); //required
    		
            //clv.setVerificationType(clvtype); ???
           
        	//clv.setChangeDate(new Date()); //DON'T SET THIS!!! it will overwritten the registration date!
        	
        	//CLEAR does not have VAFacility
//        	VAFacility vafac = (VAFacility)this.getLookup(VAFacility.class, VAFacility. CODE_HEC.getName());
//        	clv.setChangeSite(vafac);
*/
    
    
    
    //convert to code so that the case sensitive is not an issue 
    //e.g. incoming Other, on file OTHER
    private List<String> getCodes(List<String> names) {
    	if (names == null || names.size()==0)
    		return null;
    	
    	if (codeMap.size() == 0) {
	    	codeMap.put("DOD", "1");
	    	codeMap.put("NPRC", "2");
	    	codeMap.put("DPRIS", "3");
	    	codeMap.put("OMPF", "4");
	    	codeMap.put("USMC", "5");
	    	codeMap.put("CDC", "6");
	    	codeMap.put("OTHER", "7");
    	}
    	
    	List<String> codes = new ArrayList();
    	String code = null;
    	for (String name : names) {
    		codes.add((String)codeMap.get(name.toUpperCase())); //convert to upper case
    	}
    	
    	return codes;
    	
    }

    /* (non-Javadoc)
     * @see gov.va.med.fw.io.RawFileDataContainer#getRawFileData()
     */
    public OrderedMap getRawFileData() throws Exception
    {
        // no op as this class is used only for parsing data from a input file
        return null;
    }

    
	/**
	 * Validate all the required fields
	 * @return
	 */
	private String isDataValid(){ //these are required data fields
		StringBuffer err = new StringBuffer();
		
		if (StringUtils.isEmpty(firstName))
			err.append("First Name is Missing! ");
		if (StringUtils.isEmpty(lastName))
			err.append("Last Name is Missing! ");
		if (StringUtils.isEmpty(ssn))
			err.append("SSN is Missing! ");
		if (StringUtils.isEmpty(dob))
			err.append("Date of Birth is Missing! ");
		if (StringUtils.isEmpty(gender)) //gender is optional for IdM traits search
			err.append("Gender is Missing! ");
		
		return err.toString();

	}

	
	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public String getSsn() {
		return ssn;
	}

	public void setSsn(String ssn) {
		this.ssn = ssn;
	}

	public String getDob() {
		return dob;
	}

	public void setDob(String dob) {
		this.dob = dob;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}	

	public String getCleIndicator() {
		return cleIndicator;
	}

	public void setCleIndicator(String cleIndicator) {
		this.cleIndicator = cleIndicator;
	}

	public String getVerifiedMethod() {
		return verifiedMethod;
	}

	public void setVerifiedMethod(String verifiedMethod) {
		this.verifiedMethod = verifiedMethod;
	}

	public String getComments() {
		return comments;
	}

	public void setComments(String comments) {
		this.comments = comments;
	}

	public String getClRegistrationDate() {
		return clRegistrationDate;
	}

	public void setClRegistrationDate(String clRegistrationDate) {
		this.clRegistrationDate = clRegistrationDate;
	}

	public String getIcn() {
		return icn;
	}

	public void setIcn(String icn) {
		this.icn = icn;
	}





}
