package lu.tudor.santec.gecamed.esante.gui.webservice;

import lu.tudor.santec.gecamed.core.utils.GECAMedUtils;
import lu.tudor.santec.gecamed.esante.gui.dialogs.LoginDialog;
import lu.tudor.santec.gecamed.esante.gui.luxtrust.UserInactivityMonitor;
import lu.tudor.santec.gecamed.esante.utils.exceptions.SendingStoppedException;

import org.apache.log4j.Logger;


/**
 * @author jens.ferring(at)tudor.lu
 * 
 * @version
 * <br>$Log: WebserviceException.java,v $
 * <br>Revision 1.13  2014-02-18 13:17:33  ferring
 * <br>Patients with Luxembourg ID, but without DSP, are now connected to their DSP or Luxembourg ID is removed, if no DSP was found.
 * <br>If only one DSP was found in search, the compare DSP and patient dialog is shown directly.
 * <br>
 * <br>Revision 1.12  2014-02-06 14:31:33  ferring
 * <br>Exception type added
 * <br>
 * <br>Revision 1.11  2014-02-04 10:08:19  ferring
 * <br>eSante ID management completed
 * <br>Only those documents will be shown, that are retrieved by the RSQ
 * <br>
 * <br>Revision 1.10  2014-01-28 14:07:44  ferring
 * <br>Exception added
 * <br>
 * <br>Revision 1.9  2014-01-23 15:03:07  ferring
 * <br>option added to query by DSP ID
 * <br>
 * <br>Revision 1.8  2014-01-22 14:38:05  ferring
 * <br>Login information will only be reseted, if the user has no valid SAML assertion
 * <br>
 * <br>Revision 1.7  2014-01-16 12:28:44  ferring
 * <br>Changes on eSanté platform applied and logging added
 * <br>
 * <br>Revision 1.6  2013-12-17 08:39:36  ferring
 * <br>Document not found exception caught and dialog shown
 * <br>
 * <br>Revision 1.5  2013-12-16 12:05:12  ferring
 * <br>logging eSanté actions
 * <br>
 * <br>Revision 1.4  2013-12-13 15:02:24  ferring
 * <br>Exception handling changed
 * <br>
 * <br>Revision 1.3  2013-12-13 12:31:31  ferring
 * <br>Exception handling changed
 * <br>
 * <br>Revision 1.2  2013-11-29 09:10:52  ferring
 * <br>first changes for eSanté test platform
 * <br>
 * <br>Revision 1.1  2013-06-10 12:58:22  ferring
 * <br>typo in package name corrected
 * <br>
 * <br>Revision 1.1  2013-06-10 08:22:08  ferring
 * <br>eSante POC
 * <br>
 */

public class WebserviceException extends Exception
{
	/* ======================================== */
	// CONSTANTS
	/* ======================================== */
	
	private static final long	serialVersionUID	= 823740430765980848L;
	
	
	/* ---------------------------------------- */
	// ERROR TYPES
	/* ---------------------------------------- */
	
	public static final int	TYPE_UNKNOWN					= -1;
	public static final int	TYPE_SERVER						=  0;
	public static final int	TYPE_INVALID_LOGIN_DATA			=  1;
	public static final int	TYPE_NOT_AUTHORIZED				=  2;
	/** The presence password that has been provided is not correct */
	public static final int	TYPE_INVALID_PRESENCE_PASS		=  3;
	public static final int	TYPE_TIME_OUT_OF_SYNC			=  4;
	public static final int	TYPE_MANDATE_ALREADY_EXISTS		=  5;
	/** The requested document was not found on the electronic health record */
	public static final int	TYPE_DOCUMENT_NOT_AVAILABLE		=  6;
	public static final int	TYPE_INVALID_AUTHENTIFICATION	=  7;
	public static final int	TYPE_CLIENT						=  8;
	public static final int	TYPE_PROFESSINOAL_NOT_FOUND		=  9;
	public static final int	TYPE_INVALID_VALUE_IN_REQUEST	= 10;
	public static final int	TYPE_INVALID_EHEALTH_ID			= 11;
	public static final int	TYPE_PATIENT_NOT_FOUND			= 12;
	public static final int	TYPE_EMR_NOT_FOUND				= 13;
	/** The user who issued the webservice request was not authorized to use the functionality  */
	public static final int	TYPE_USER_NOT_AUTHORIZED		= 14;
	/** The user does not have sufficient permissions for uploading a specific document type */
	public static final int	TYPE_DENIED_BY_RIGHT_SERVICE	= 15;
	/** The security token was not recognized. Usually means the LT-card is not known to the platform. */
	public static final int	TYPE_FAILED_AUTHENTICATION		= 16;
//	public static final int	TYPE_	= 1;
	
	
	/* ---------------------------------------- */
	// ERROR CODES
	/* ---------------------------------------- */
	
	// technical errors
	public static final String ERROR_CODE_SERVER				= "soap:Server";
	public static final String ERROR_CODE_CLIENT				= "soap:Client";
	
	// WSDL errors
	public static final String ERROR_CODE_SUCCESS				= "urn:oasis:names:tc:SAML:2.0:status:Success";
	public static final String ERROR_CODE_ERROR					= "Error";
	public static final String ERROR_CODE_WARNING				= "Warning";
	public static final String ERROR_CODE_REQUEST_DENIED		= "urn:oasis:names:tc:SAML:2.0:status:RequestDenied";
	public static final String ERROR_CODE_INVALID_ATTRIBUTE		= "urn:oasis:names:tc:SAML:2.0:status:InvalidAttrNameOrValue";
	public static final String ERROR_CODE_RESPONSE_FAILURE		= "urn:oasis:names:tc:ebxml-regrep:ResponseStatusType:Failure";
	public static final String ERROR_CODE_REQUEST_UNSUPPORTED	= "urn:oasis:names:tc:SAML:2.0:status:RequestUnsupported";
	public static final String ERROR_CODE_FAILED_AUTHENTICATION	= "ns1:FailedAuthentication";
	
	/* ---------------------------------------- */
	// ERROR MESSAGES
	/* ---------------------------------------- */
	
	public static final String ERROR_MSG_AUTHORIZATION_FAILED_MSG	= "The security token could not be authenticated or authorized";
	public static final String ERROR_MSG_CLIENT_TIME_OUT_OF_SYNC	= "The message has expired";
	public static final String ERROR_MSG_ACCESS_FORBIDDEN			= "AccessForbidden";
	public static final String ERROR_MSG_PROFESSION_NOT_FOUND		= "ProfessionalNotFound";
	public static final String ERROR_MSG_MANDATE_ALREADY_EXISTS		= "MandateAlreadyExist";
	public static final String ERROR_MSG_MESSAGE_EXPIRED			= "The message has expired";
	public static final String ERROR_MSG_INVALID_PRESENCE_PASSWORD	= "InvalidPresencePassword";
	public static final String ERROR_MSG_DOCUMENT_UNIQUE_ID			= "XDSDocumentUniqueIdError";
	public static final String ERROR_MSG_INVALID_AUTHENTIFICATION	= "InvalidAuthentification";
	public static final String ERROR_MSG_INVALID_VALUE_IN_REQUEST	= "InvalidValueInRequest";
	public static final String ERROR_MSG_PATIENT_NOT_FOUND			= "PatientNotFound";
	public static final String ERROR_MSG_DSP_NOT_FOUND				= "EmrNotFound";
	public static final String ERROR_MSG_REQUEST_UNAUTHORIZED	    = "XDSUnauthorizedRequest";
	public static final String ERROR_MSG_DENIED_BY_RIGHT_SERVICE    = "XDSAccessDeniedByRightsService";
	
	// !!! Don't look for the details, because they're multilingual !!! 
	
	
	
	/* ======================================== */
	// MEMBERS
	/* ======================================== */
	
	/** the logger Object for this class */
	private static Logger logger = Logger.getLogger(WebserviceException.class.getName());
	
	
	private SoapSender	sender;
	
	private String		xmlResponse;
	
	private int			errorType;
	
	
	/* ======================================== */
	// CONSTRUCTORS
	/* ======================================== */
	
	public WebserviceException (SoapSender sender, Throwable cause)
	{
		super(sender.getErrorMessage(), cause);
		this.sender			= sender;
		try
		{
			// Obtain the message part of the response from the server
			this.xmlResponse	= sender.getResponseMessage();
		}
		catch (SendingStoppedException e)
		{
			logger.error(e.getMessage());
		}
		defineErrorType();
	}
	
	
	public WebserviceException (SoapSender sender)
	{
		this(sender, null);
	}
	
	
	
	/* ======================================== */
	// GETTER
	/* ======================================== */
	
	public String getCode ()
	{
		return sender.getErrorCode();
	}
	
	
	public String getDetails ()
	{
		return sender.getErrorDetail();
	}
	
	
	public int getErrorType ()
	{
		return errorType;
	}
	
	
	public SoapSender getSender ()
	{
		return sender;
	}
	
	
	@Override
	public String getMessage ()
	{
		return sender.getErrorMessage();
	}
	
	
	public String getXmlResponse ()
	{
		return xmlResponse;
	}
	
	
	
	/* ======================================== */
	// HELP METHODS
	/* ======================================== */
	
	/**
	 * Analysis the error code, error message and error details and defines the 
	 * error type out of this information.
	 */
	private void defineErrorType ()
	{
		String errorCode = sender.getErrorCode();
		
		
		if (GECAMedUtils.isEmpty(errorCode))
		{
			errorType = TYPE_UNKNOWN;
		}
		else if (ERROR_CODE_SERVER.equals(errorCode))
		{
			if (!GECAMedUtils.isEmpty(getMessage()))
			{
				if (ERROR_MSG_AUTHORIZATION_FAILED_MSG.equals(getMessage()))
					errorType	= TYPE_INVALID_LOGIN_DATA;
				else if (ERROR_MSG_MESSAGE_EXPIRED.equals(getMessage()))
					errorType	= TYPE_TIME_OUT_OF_SYNC;
				else
					errorType	= TYPE_SERVER;
			}
			else
			{
				errorType = TYPE_SERVER;
			}
			LoginDialog.resetConfiguration();
		}
		else if (ERROR_CODE_REQUEST_DENIED.equals(errorCode))
		{
			if (ERROR_MSG_PROFESSION_NOT_FOUND.equals(getMessage()))
			{
				errorType	= TYPE_PROFESSINOAL_NOT_FOUND;
				LoginDialog.resetConfiguration();
			}
			else if (ERROR_MSG_ACCESS_FORBIDDEN.equals(getMessage()))
			{
				errorType	= TYPE_NOT_AUTHORIZED;
			}
			else if (ERROR_MSG_MANDATE_ALREADY_EXISTS.equals(getMessage()))
			{
				errorType	= TYPE_MANDATE_ALREADY_EXISTS;
			}
			else if (ERROR_MSG_INVALID_PRESENCE_PASSWORD.equals(getMessage()))
			{
				errorType	= TYPE_INVALID_PRESENCE_PASS;
			}
			else if (ERROR_MSG_INVALID_AUTHENTIFICATION.equals(getMessage()))
			{
				errorType	= TYPE_INVALID_AUTHENTIFICATION;
			}
			else if (ERROR_MSG_DSP_NOT_FOUND.equals(getMessage()))
			{
				errorType	= TYPE_EMR_NOT_FOUND;
			}
			
			else
			{
				errorType	= TYPE_NOT_AUTHORIZED;
			}
		}
		else if (ERROR_CODE_RESPONSE_FAILURE.equals(errorCode))
		{
			if(ERROR_MSG_REQUEST_UNAUTHORIZED.equals(getMessage())){
				errorType = TYPE_USER_NOT_AUTHORIZED;
			}
			
			
			else if (ERROR_MSG_DENIED_BY_RIGHT_SERVICE.equals(getMessage()))
			{
				errorType	= TYPE_DENIED_BY_RIGHT_SERVICE;
			}
			else if (ERROR_MSG_DOCUMENT_UNIQUE_ID.equals(getMessage()))
			{
				errorType	= TYPE_DOCUMENT_NOT_AVAILABLE;
			}
			else
			{
				errorType	= TYPE_UNKNOWN;
			}
		}
		else if (ERROR_CODE_CLIENT.equals(errorCode))
		{
			if (getMessage().startsWith("AUTH_X509_UNTRUSTED "))
			{
				errorType = TYPE_INVALID_LOGIN_DATA;
				LoginDialog.resetConfiguration();
			}
			else if (ERROR_MSG_CLIENT_TIME_OUT_OF_SYNC.equals(sender.getErrorDetail()))
			{
				errorType = TYPE_TIME_OUT_OF_SYNC;
			}
			else
			{
				errorType = TYPE_CLIENT;
			}
		}
		else if (ERROR_CODE_REQUEST_UNSUPPORTED.equals(errorCode))
		{
			if (ERROR_MSG_INVALID_VALUE_IN_REQUEST.equals(getMessage()))
			{
				String details	= sender.getErrorDetail();
				if (details != null 
						&& details.contains("Subject>NameId")
						&& details.contains("(usernameToken)"))
				{
					errorType	= TYPE_INVALID_EHEALTH_ID;
				}
				else
				{
					errorType	= TYPE_INVALID_VALUE_IN_REQUEST;
				}
			}
			else
			{
				errorType	= TYPE_UNKNOWN;
			}
		}
		else if (ERROR_MSG_PATIENT_NOT_FOUND.equals(sender.getErrorMessage()))
		{
			errorType = TYPE_PATIENT_NOT_FOUND;
		}
		else if (ERROR_MSG_CLIENT_TIME_OUT_OF_SYNC.equals(sender.getErrorDetail()))
		{
			errorType = TYPE_TIME_OUT_OF_SYNC;
		}
		else if (ERROR_CODE_FAILED_AUTHENTICATION.equals(errorCode))
		{
			errorType = TYPE_FAILED_AUTHENTICATION;
		}
		
		
		else
		{
			errorType = TYPE_UNKNOWN;
		}
		
		if (errorType == TYPE_UNKNOWN && !Security.hasValidSamlAssertion()){
			UserInactivityMonitor.logout("esante.eSanteTab.logout.unknownExceptionLogoutMessage");
		}
	}
}
