package gov.va.med.fw.ui.security;

//Java imports
import gov.va.med.fw.security.EncryptionServiceException;
import gov.va.med.fw.security.EncryptionServiceImpl;
import gov.va.med.fw.security.KeyCache;
import gov.va.med.fw.util.StringUtils;

import javax.crypto.SecretKey;
import javax.servlet.ServletRequest;
import javax.servlet.jsp.JspException;

/**
 * This helper class is intended to be used by tags and decryption filter
 * to encrypt and decrypt the information.
 *
 * @author Muddaiah Ranga
 * @version 3.0
 */
public class UIEncryptionServiceImpl extends EncryptionServiceImpl implements UIEncryptionService 
{
    private static final char PLUS_SIGN = '+';
    private static final char MINUS_SIGN = '-';
    private static final char EQUAL_SIGN = '=';
    private static final char UNDERSCORE_SIGN = '_';

    protected String encryptionErrorUrl;
    
	/**
	 * Gets the encryption error page Url.
	 */
	public String getEncryptionErrorUrl()
	{
		return encryptionErrorUrl;
	}

	/**
	 * Sets the encryption error page Url.
	 */
	public void setEncryptionErrorUrl(String pEncryptionErrorUrl)
	{
		encryptionErrorUrl = pEncryptionErrorUrl;
	}

	/**
	 * Encrypt the query string part of the url.
	 *
	 * @param request the request object
	 * @param value the url to be encrypted
	 * @return encrypted url
	 *
	 * @throws JspException
	 */
    public String encryptQueryString(ServletRequest request, String value)
    throws JspException
    {
        //If encryption flag is set to false, do nothing and return.
        if(!isEncryptionEnabled()) return value;
        String url = value;
        try
		{
            int indexOfQuestion = value.indexOf("?");
            if( indexOfQuestion > 0 )
            {
            		String uri = value.substring(0,indexOfQuestion + 1);
                   String qs = value.substring(indexOfQuestion + 1);

                   //Replace html entities like "&amp;" with "&" and the like ...
                    qs = StringUtils.replaceHtmlEntities(qs);

                    String encryptedQs = this.encrypt(request,qs);
                    url = uri + QUERY_STRING_EQUAL + encryptedQs;
            }
		}
        catch(EncryptionServiceException ex)
		{
        	throw new JspException(ex);
		}
        return url;
    }
    
	/**
	 * Encrypt the query string part of the hidden field.
	 *
	 * @param request the request object
	 * @param value the hidden field value to be encrypted
	 * @return encrypted value
	 *
	 * @throws JspException
	 */
    public String encryptHiddenField(ServletRequest request,String value)
    throws JspException
    {
        //If encryption flag is set to false, do nothing and return.
        if(!isEncryptionEnabled()) return value;
        String encryptedFieldValue = value;
        try
		{
        	//If encryption flag is set true, encrypt the query string.
        	if(value != null && value.length() > 0)
        	{
                String encryptedValue = this.encrypt(request,value);
                encryptedFieldValue = HIDDEN_FIELD_COLAN + encryptedValue;
            }
		}
        catch(EncryptionServiceException ex)
		{
        	throw new JspException(ex);
        }
        return encryptedFieldValue;
    }
    
    /**
     * Wrapper for the method <code>EncryptionService.encrypt()</code>.
     *
     * @param request the request object
     * @param clearText the test to be encrypted
     * @return the encrypted text
     * @throws EncryptionServiceException thrown when there was an encryption error
     */
    public String encrypt(ServletRequest request, String clearText)
    throws EncryptionServiceException
    {
    	String encryptedText = clearText;
    	if(request instanceof KeyCache)
    	{
    		//Get the secret key from key cache, if not found create a new one.
    		SecretKey key = getSecretKey((KeyCache)request,true);
    		if(key != null)
    		{
    			encryptedText = super.encrypt(key,request.getCharacterEncoding(),clearText);
    			//replace the plus sign with pound sign
    			encryptedText = encryptedText.replace(PLUS_SIGN,MINUS_SIGN).replace(EQUAL_SIGN,UNDERSCORE_SIGN);
    		}
        }
        return encryptedText;
    }

    /**
     * Wrapper for the method <code>EncryptionService.decrypt()</code>
     *
     * @param request the request object
     * @param encryptedText the encrypted text
     * @return the decrypted text
     * @throws EncryptionServiceException thrown when there was a decryption error
     */
    public String decrypt(ServletRequest request, String encryptedText)
    throws EncryptionServiceException
    {
    	String clearText = encryptedText;
    	if(request instanceof KeyCache)
    	{
    		//Get the secret key from key cache, if not found donot create.
    		SecretKey key = getSecretKey((KeyCache)request,false);
    		if(key != null)
    		{
    			String encrypted = encryptedText.replace(MINUS_SIGN, PLUS_SIGN).replace(UNDERSCORE_SIGN, EQUAL_SIGN);
    			clearText = super.decrypt(key,request.getCharacterEncoding(),encrypted);
    		}
    	}
        return clearText;
    }
}
