
package gov.va.med.cds.request.vista.write;

import static gov.va.med.cds.exception.ErrorCodeEnum.NO_PATIENT_IDS_REQUESTED;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.dom4j.Element;

import gov.va.med.cds.clinicaldata.DomainEntryPoint;
import gov.va.med.cds.common.person.correlation.PersonIdentifier;
import gov.va.med.cds.common.person.correlation.PersonIdentifierInterface;
import gov.va.med.cds.exception.ErrorCodeEnum;
import gov.va.med.cds.filter.EntryFilterInterface;
import gov.va.med.cds.request.ValidationException;

public class CdsWrite implements CdsWriteInterface {
	private String templateId;
	private DomainEntryPoint domainEntryPoint;
	private String requestId;
	private Element parentDataElement;
	private List<PersonIdentifierInterface> personIdentifiers = null;
	private List<EntryFilterInterface> writeData = null;
	private String entryPointElement = null;
	private Map<String, String> templateEntryPointMap = null;

	public void setTemplateEntryPointMap(Map<String, String> templateEntryPointMap) {
		this.templateEntryPointMap = templateEntryPointMap;
	}

	public List<EntryFilterInterface> getWriteData() {
		return writeData;
	}
	
    public void extractData()
    {
		List<Element> dataElementsList = this.parentDataElement.elements(templateEntryPointMap.get(String.format( "%s-%s", templateId, domainEntryPoint.getName())));
		
		extractPatientIdentifiers(dataElementsList);
		extractCreateData(dataElementsList);
    }
    
	public void setDomainEntryPoint(DomainEntryPoint domainEntryPoint) {
		this.domainEntryPoint = domainEntryPoint;
	}

	public void setTemplateId(String templateId) {
		this.templateId = templateId;
	}

	public void setRequestId(String requestId) {
		this.requestId = requestId;
	}
		
	public List<PersonIdentifierInterface> getPersonIdentifiers() 
	{
		 return personIdentifiers;
	}
	
	public String getDomainEntryPoint() {
		return this.domainEntryPoint.getName();
	}

	public String getRequestId() {
		return this.requestId;
	}

	/**
	 * Gets the template identifier for the filter request.
	 * 
	 * @return The template identifier.
	 */
	public String getTemplateId() {
		return this.templateId;
	}	
	
	private void extractPatientIdentifiers(List<Element> accessEventElementsList) 
	{

		PersonIdentifierInterface patientIdentifier = new PersonIdentifier();
		personIdentifiers = new ArrayList();

		for (Element accessEvent : accessEventElementsList) {
			Element patient = accessEvent.element("patient");
			if (patient == null) {
				 throw new ValidationException( NO_PATIENT_IDS_REQUESTED );
			
			}
			Element identitifier = patient.element("identifier");
			
			patientIdentifier.setAssigningAuthority(identitifier.element("assigningAuthority").getTextTrim());
			if (patientIdentifier.getAssigningAuthority() == null
					|| patientIdentifier.getAssigningAuthority().isEmpty()) {
				throw new ValidationException(ErrorCodeEnum.PATIENT_ID_MISSING_ASSIGNING_AUTHORITY);
			}
			patientIdentifier.setAssigningFacility(identitifier.element("assigningFacility").getTextTrim());
			if (patientIdentifier.getAssigningFacility() == null
					|| patientIdentifier.getAssigningFacility().isEmpty()) {
				throw new ValidationException(ErrorCodeEnum.PATIENT_ID_MISSING_ASSIGNING_FACILITY);
			}
			patientIdentifier.setIdentity(identitifier.element("identity").getTextTrim());
			if (patientIdentifier.getIdentity() == null || patientIdentifier.getIdentity().isEmpty()) {
				throw new ValidationException(ErrorCodeEnum.PATIENT_ID_MISSING_IDENTITY);
			}

			personIdentifiers.add(patientIdentifier);
		}

	}

	public List<EntryFilterInterface> getCreateData() {
	
		return writeData;
	
	}
	
	private void extractCreateData(List<Element> dataList) {
		writeData = new ArrayList();
		for (Element record : dataList) {
		EntryFilterInterface dataObj = new CdsWriteData(record, this.templateId, this.requestId, this.domainEntryPoint.getName(), this.personIdentifiers);
		writeData.add(dataObj);
		}
	}
	public void setEntryPointElement(String entryPointElement) {
		this.entryPointElement = entryPointElement;
	}
	
	public void setDataElement(Element parentDataElement) {
		this.parentDataElement = parentDataElement;
	}
}
