package com.agilex.healthcare.schedulingmanager.mdws;

import java.util.UUID;

import com.agilex.healthcare.schedulingmanager.mdws.generatedwsdl.schedulingservice.FaultTO;

public class MdwsResponseException extends RuntimeException {
	private static final long serialVersionUID = 3456753855011898482L;
	private static final org.apache.commons.logging.Log logger = org.apache.commons.logging.LogFactory.getLog(MdwsResponseException.class);

	private String uuid = UUID.randomUUID().toString();
	private String expandedMessage;
	private UserMessages userMessage;

//----------------------------------------------------------------------------------------------------------------------

	public enum UserMessages {
		INVALID_WSDL("Invalid Server Configuration"),
		INVALID_PATIENT("Invalid Patient"),
		CONNECTION_ERROR("Unable to connect to Vista system"),
		INVALID_FACILITY_CODE("The facility code provided was not valid."),
		INVALID_ACCESS_VERIFY("You have entered an invalid username or password!"),
		INVALID_INPUT("The input received was not valid."),
		TIMEOUT("Service timed out, please re-try."),
		CONNECTIONS_NOT_READY("Connectivity with mdws was lost, please logout and login again"),
		INVALID_DATA_RETURNED("An Error Occurred with Invalid Data Returned"),
		GENERIC_ERROR("An Error Occurred");

		private final String value;

		private UserMessages(String value) {
			this.value = value;
		}

		@Override
		public String toString() {
			return this.value;
		}
	}

	public enum MdwsResponseExceptionLogType {DEBUG, INFO, WARN, ERROR}
	/**
	 * Depending on the type of error, the message will be written out as debug, info, warn, or error.
	 * The return value indicates what the type of message was.
	 */
	public static MdwsResponseExceptionLogType logException(org.apache.commons.logging.Log exceptionLogger, MdwsResponseException exception) {
		MdwsResponseExceptionLogType messageType = MdwsResponseExceptionLogType.ERROR;
		switch (exception.userMessage) {
			case INVALID_WSDL:
			case CONNECTION_ERROR:
			case GENERIC_ERROR:
			case INVALID_FACILITY_CODE:
				exceptionLogger.error(exception.expandedMessage);
				messageType = MdwsResponseExceptionLogType.ERROR;
			break;

			case INVALID_PATIENT:
				exceptionLogger.warn(exception.expandedMessage);
				messageType = MdwsResponseExceptionLogType.WARN;
			break;

			case TIMEOUT:
			case CONNECTIONS_NOT_READY:
			case INVALID_ACCESS_VERIFY:
			case INVALID_INPUT:
			case INVALID_DATA_RETURNED:
				exceptionLogger.info(exception.expandedMessage);
				messageType = MdwsResponseExceptionLogType.INFO;
			break;

			default:
				exceptionLogger.error(exception.expandedMessage);
				messageType = MdwsResponseExceptionLogType.ERROR;
			break;
		}

		return messageType;
	}

//----------------------------------------------------------------------------------------------------------------------

	/**
	 *
	 * @param message The message to display to an end user
	 * @param expandedMessage A more detailed message that a developer would want to know.
	 */
	public MdwsResponseException(UserMessages message, String expandedMessage) {
		super(message == null ? UserMessages.GENERIC_ERROR.toString() : message.toString());
		this.userMessage = message;
		this.expandedMessage = String.format("UUID: %s%n%s%nAdditional Info: %s", uuid, message == null ? UserMessages.GENERIC_ERROR.toString() : message.toString(), expandedMessage);
		MdwsResponseException.logException(logger, this);
	}

	/**
	 *
	 * @param message The message to display to an end user
	 * @param fault A MDWS FaultTO with the reason for a failure in MDWS code.
	 */
	public MdwsResponseException(UserMessages message, com.agilex.healthcare.schedulingmanager.mdws.generatedwsdl.schedulingservice.FaultTO fault) {
		super(message == null ? UserMessages.GENERIC_ERROR.toString() : message.toString());
		this.userMessage = message;
		this.expandedMessage = String.format("UUID: %s%n%s%nAdditional Info: %s", uuid, message == null ? UserMessages.GENERIC_ERROR.toString() : message.toString(), fault.getMessage());
		MdwsResponseException.logException(logger, this);
	}

    /**
     *
     * @param message The message to display to an end user
     * @param fault A MDWS FaultTO with the reason for a failure in MDWS code.
     */
    public MdwsResponseException(UserMessages message, com.agilex.healthcare.schedulingmanager.mdws.generatedwsdl.emrservice.FaultTO fault) {
        super(message == null ? UserMessages.GENERIC_ERROR.toString() : message.toString());
        this.userMessage = message;
        this.expandedMessage = String.format("UUID: %s%n%s%nAdditional Info: %s", uuid, message == null ? UserMessages.GENERIC_ERROR.toString() : message.toString(), fault.getMessage());
        MdwsResponseException.logException(logger, this);
    }

    /**
    *
    * @param message The message to display to an end user
    * @param fault A MDWS FaultTO with the reason for a failure in MDWS code.
    */
   public MdwsResponseException(UserMessages message, com.agilex.healthcare.schedulingmanager.mdws.generatedwsdl.queryservice.FaultTO fault) {
       super(message == null ? UserMessages.GENERIC_ERROR.toString() : message.toString());
       this.userMessage = message;
       this.expandedMessage = String.format("UUID: %s%n%s%nAdditional Info: %s", uuid, message == null ? UserMessages.GENERIC_ERROR.toString() : message.toString(), fault.getMessage());
       MdwsResponseException.logException(logger, this);
   }


    /**
     *
     * @param fault A MDWS FaultTO with the reason for a failure in MDWS code - this is parsed to try creating
     * a message to show the end user - SEE @link {@link MdwsResponseFaultTOFilter}.
     */
    public MdwsResponseException(com.agilex.healthcare.schedulingmanager.mdws.generatedwsdl.emrservice.FaultTO fault) {
        super(MdwsResponseFaultTOFilter.filterFault(fault).toString());
        this.userMessage = MdwsResponseFaultTOFilter.filterFault(fault);
        this.expandedMessage = String.format("UUID: %s%n%s%nAdditional Info: %s", uuid, this.getMessage(), fault.getMessage());
        MdwsResponseException.logException(logger, this);
    }

    /**
    *
    * @param fault A MDWS FaultTO with the reason for a failure in MDWS code - this is parsed to try creating
    * a message to show the end user - SEE @link {@link MdwsResponseFaultTOFilter}.
    */
   public MdwsResponseException(com.agilex.healthcare.schedulingmanager.mdws.generatedwsdl.queryservice.FaultTO fault) {
       super(MdwsResponseFaultTOFilter.filterFault(fault).toString());
       this.userMessage = MdwsResponseFaultTOFilter.filterFault(fault);
       this.expandedMessage = String.format("UUID: %s%n%s%nAdditional Info: %s", uuid, this.getMessage(), fault.getMessage());
       MdwsResponseException.logException(logger, this);
   }


    /**
	 *
	 * @param fault A MDWS FaultTO with the reason for a failure in MDWS code - this is parsed to try creating
	 * a message to show the end user - SEE @link {@link MdwsResponseFaultTOFilter}.
	 */
	public MdwsResponseException(FaultTO fault) {
		super(MdwsResponseFaultTOFilter.filterFault(fault).toString());
		this.userMessage = MdwsResponseFaultTOFilter.filterFault(fault);
		this.expandedMessage = String.format("UUID: %s%n%s%nAdditional Info: %s", uuid, this.getMessage(), fault.getMessage());
		MdwsResponseException.logException(logger, this);
	}

//----------------------------------------------------------------------------------------------------------------------

	public String getUuid() {
		return uuid;
	}

	public String getExpandedMessage() {
		return expandedMessage;
	}

	public void setExpandedMessage(String expandedMessage) {
		this.expandedMessage = expandedMessage;
	}

	public UserMessages getUserMessage() {
		return userMessage;
	}

//----------------------------------------------------------------------------------------------------------------------

	@Override
	public String toString() {
		return this.expandedMessage;
	}
}
