package com.agilex.healthcare.schedulingmanager.mdws.translator;

import com.agilex.healthcare.mobilehealthplatform.domain.DOBDate;
import com.agilex.healthcare.mobilehealthplatform.domain.Patient;
import com.agilex.healthcare.mobilehealthplatform.domain.PatientIdentifier;
import com.agilex.healthcare.schedulingmanager.mdws.MdwsDateTranslationUtil;
import com.agilex.healthcare.schedulingmanager.mdws.MdwsResponseException;
import com.agilex.healthcare.schedulingmanager.mdws.generatedwsdl.schedulingservice.HospitalLocationTO;
import com.agilex.healthcare.schedulingmanager.mdws.generatedwsdl.schedulingservice.PatientTO;
import com.agilex.healthcare.utility.DateHelper;
import com.agilex.healthcare.utility.NullChecker;

import java.util.Date;

public class PatientTranslator {

	public Patient translate(PatientTO mdwsPatient) {
		if (mdwsPatient == null)
			throw new MdwsResponseException(MdwsResponseException.UserMessages.INVALID_DATA_RETURNED, "PatientTO was null");
		if (mdwsPatient.getFault() != null)
			throw new MdwsResponseException(mdwsPatient.getFault());

		String patientName = mdwsPatient.getPatientName();
		String gender = mdwsPatient.getGender();
		String ssn = mdwsPatient.getSsn();
		String localPid = mdwsPatient.getLocalPid();
		//boolean inpatient = mdwsPatient.isInpatient();
		boolean serviceConnected = mdwsPatient.isServiceConnected();
		int scPercent = mdwsPatient.getScPercent();
		String serviceConnectedPercent = String.valueOf(scPercent);
		String cwad = mdwsPatient.getCwad();
		boolean restricted = mdwsPatient.isRestricted();
		String mpiPid = mdwsPatient.getMpiPid();
		String admitTimestamp = mdwsPatient.getAdmitTimestamp();
		
		HospitalLocationTO location = mdwsPatient.getLocation();
		//Perform Error Checking
		if (location != null && location.getFault() != null)
			throw new MdwsResponseException(location.getFault());
		
		Patient patient = new Patient();
		patient.setDisplayName(patientName);
		patient.setGender(gender);
		patient.setSsn(ssn);

		PatientIdentifier patientIdentifier = new PatientIdentifier("default", localPid);
		patient.setPatientIdentifier(patientIdentifier);

		setDateOfBirth(patient, mdwsPatient);
		setPatientAge(patient, mdwsPatient);
		setPatientNames(patient, mdwsPatient);
		setPatientMiddleInitial(patient);
		
		//NOTICE this differs from the PatientTranslator implemention in MDWSLib where we don't do this check for id
		//or default inPatient to true if there is a location but set it based on whether inpatient was returned from
		//mdws.
		String id = null;
		if (location != null)
			id = location.getId();
		if ((location != null) && (id != null) && (!id.isEmpty())) {
			patient.setLocationIEN(id);
			String name = location.getName();
			patient.setWardLocation(name);
			String room = location.getRoom();
			patient.setRoombed(room);
			patient.setInpatient(true);
		}
		//patient.setInpatient(inpatient);
		patient.setServiceConnected(serviceConnected);
		patient.setServiceConnectedPercent(serviceConnectedPercent);
		patient.setCwad(cwad);
		patient.setSensitive(restricted);
		if (mpiPid != null)
            patient.setIcn(mpiPid);
        if (admitTimestamp != null && admitTimestamp.length() > 0) {
            Date parseVistaDateTime = DateHelper.parseVistaDateTime(admitTimestamp);
			patient.setAdmittedDateTime(parseVistaDateTime);
        }
		return patient;
	}

	private void setPatientAge(Patient patient, PatientTO mdwsPatient) {
		try {
			int age = mdwsPatient.getAge();
			if (age == 0) {
				long calculatedAge = calculateAge(patient.getDateOfBirth().getDate());
				patient.setAge(String.valueOf(calculatedAge));
			}
		} catch (Exception e) {}

	}

	private long calculateAge(Date dob) {
		return DateHelper.calculateDeltaInYears(dob, new Date());
	}

	private void setPatientNames(Patient patient, PatientTO mdwsPatient) {
		// Assuming "LAST,FIRST MIDDLE" Syntax
		String patientName = mdwsPatient.getPatientName();
		if (NullChecker.isNotNullish(patientName)) {
			String[] splitNames = patientName.trim().split(",");
			patient.setLastName(splitNames[0]);
			String[] firstAndMiddle = splitNames[1].toString().trim().split(" ");

			switch (firstAndMiddle.length) {
                case 1:
                    patient.setFirstName(firstAndMiddle[0]);
                    break;
                case 2:
                    patient.setFirstName(firstAndMiddle[0]);
                    patient.setMiddleName(firstAndMiddle[1]);
                    break;
                case 3: // rare, but possible
                    patient.setFirstName(firstAndMiddle[0]);
                    patient.setMiddleName(firstAndMiddle[1] + " " + firstAndMiddle[2]);
                    break;
                case 4: // even more rare, but possible
                    patient.setFirstName(firstAndMiddle[0]);
                    patient.setMiddleName(firstAndMiddle[1] + " " + firstAndMiddle[2] + " " + firstAndMiddle[3]);
                    break;
                default:
                    patient.setFirstName(firstAndMiddle[0]); // first name is required by vista;
			}
		}
	}

	private void setPatientMiddleInitial(Patient patient) {
		String middleName = patient.getMiddleName();
		if (NullChecker.isNotNullish(middleName)) {
			char initial = middleName.charAt(0);
			patient.setMiddleInitial(String.valueOf(initial).toUpperCase());
		}
	}

	private void setDateOfBirth(Patient patient, PatientTO mdwsPatient) {
		String dob = mdwsPatient.getDob();
		Date dobDate = MdwsDateTranslationUtil.extractDateOrNull(dob);
		if (dobDate == null)
			patient.setDateOfBirth(null);
		else
			patient.setDateOfBirth(new DOBDate(dobDate));
	}
}
