/********************************************************************
 * Copyright © 2005-2006 VHA. All rights reserved
 ********************************************************************/
package gov.va.med.esr.common.util;

// Java Classes
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

// Framework Classes
import gov.va.med.fw.model.lookup.Lookup;
import gov.va.med.fw.model.lookup.NamedLookup;
import gov.va.med.fw.util.StringUtils;

// ESR Classes
import gov.va.med.esr.common.infra.ImpreciseDate;
import gov.va.med.esr.common.model.party.Address;
import gov.va.med.esr.common.model.party.Email;
import gov.va.med.esr.common.model.party.Phone;
import gov.va.med.esr.common.model.party.SimpleAddress;
import gov.va.med.esr.common.model.person.Name;
import gov.va.med.esr.common.model.person.SSN;

/**
 * Various utilities to support the JSP Pages.
 *
 * @author vhaivmbapooh
 * @author Andrew Pach
 * @version 3.0
 */
public class CommonJspUtils
{
    public static final String NULL_NA_TEXT = "not applicable";
    public static final String NULL_DEFAULT_TEXT = "";
    public static final String STANDARD_DATE_FORMAT = CommonDateUtils.MMDDYYYY;
    public static final String NEW_LINE = "\n";
    public static final String LINE_BREAK = "<br>";

    /**
     * Displays a value with various formatting options depending on the type of the value being
     * passed in.
     *
     * @param value The value to format.
     * @param nullText An optional value that specifies what should be displayed for when the value
     * is null. This defaults to the empty string.
     * @param format An optional format that can be used for data types that support it.
     *
     * @return The formatted value to display.
     */
    public static String displayValue(Object value, String nullText, String format)
    {
        if (value == null) return nullText;

        String result = null;
        if (value instanceof ImpreciseDate)
            result = displayDate((ImpreciseDate)value, format);
        else
            if (value instanceof Date)
                result = displayDate((Date)value, format);
            else
                if (value instanceof Boolean)
                    result = displayBoolean((Boolean)value, format);
                else
                    if (value instanceof Name)
                        result = displayName((Name)value);
                    else
                        if (value instanceof Phone)
                            result = displayPhone((Phone)value);
                        else
                            if (value instanceof Email)
                                result = displayEAddr((Email)value);
                            else
                                if (value instanceof Address)
                                    result = displayAddress((Address)value);
                                else
                                    if (value instanceof SimpleAddress)
                                        result = displayAddress((SimpleAddress)value);
                                    else
                                        if (value instanceof NamedLookup)
                                            result = displayNamedLookup((NamedLookup)value);
                                        else
                                            if (value instanceof Lookup)
                                                result =
                                                    displayCodedDescriptionLookup((Lookup)value);
                                            else
                                                if (value instanceof SSN)
                                                    result = displaySSN((SSN)value);
                                                else
                                                    if (value != null)
                                                        result = value.toString();

        if (result == null)
            result = nullText;
        return result;
    }

    public static String displayValue(Object value, String nullText)
    {
        return displayValue(value, nullText, null);
    }

    public static String displayValues(List values, String defText, String format)
    {
        StringBuffer result = new StringBuffer();
        for (Iterator i = values.iterator(); i.hasNext();)
        {
            result.append(displayValue(i.next(), defText, format));
            result.append(i.hasNext() ? LINE_BREAK : "");
        }
        return result.toString();
    }

    public static String displayValues(Set values, String defText, String format)
    {
        return displayValues(new ArrayList(values), defText, format);
    }

    /**
     * Returns a formatted boolean value.
     *
     * @param value The boolean value to display
     * @param format The optional format to use.  The default format is 'Yes/No', however, other
     * formats can be used. Each format should be two values separated by a "/" character.  The
     * first value is the true value and the second value is the false value.
     *
     * @return The formatted boolean
     */
    private static String displayBoolean(Boolean value, String format)
    {
        String trueValue = "Yes";
        String falseValue = "No";

        if (!StringUtils.isEmpty(format))
        {
            String[] formats = format.split("/");
            if (formats.length == 2)
            {
                trueValue = formats[0];
                falseValue = formats[1];
            }
        }

        String result = null;
        if (value != null)
        {
            result = value.booleanValue() ? trueValue : falseValue;
        }
        return result;
    }

    /**
     * Returns a formatted date without the time.
     *
     * @param value The date
     * @param format An optional format
     *
     * @return The formatted date
     */
    public static String displayDate(ImpreciseDate value, String format)
    {
        return displayDate(value, format, false);
    }

    /**
     * Returns a formatted imprecise date with an optional time.
     *
     * @param value The date
     * @param format An optional format
     * @param displayTime If true, the time portion will be included.  Otherwise, only the date will
     * be returned.
     *
     * @return The formatted date
     */
    public static String displayDate(ImpreciseDate value, String format, boolean displayTime)
    {
        if (displayTime)
        {
            return CommonDateUtils.formatForDisplayWithTime(value, format);
        }
        else
        {
            return CommonDateUtils.format(value, format);
        }
    }

    /**
     * Returns a formatted date without the time.
     *
     * @param value The date
     * @param format An optional format
     *
     * @return The formatted date
     */
    public static String displayDate(Date value, String format)
    {
        return displayDate(value, format, false);
    }

    /**
     * Returns a formatted date with an optional time.
     *
     * @param value The date
     * @param format An optional format
     * @param displayTime If true, the time portion will be included.  Otherwise, only the date will
     * be returned.
     *
     * @return The formatted date
     */
    public static String displayDate(Date value, String format, boolean displayTime)
    {
        if (displayTime)
        {
            return CommonDateUtils.formatWithTime(value, format);
        }
        else
        {
            return CommonDateUtils.format(value, format);
        }
    }

    public static String displayName(Set value, String nameType)
    {
        String result = null;
        if (value == null)
            return displayValue(null, NULL_DEFAULT_TEXT);
        Iterator iter = value.iterator();
        while (iter.hasNext())
        {
            Name nameTemp = (Name)iter.next();
            if (nameTemp.getType().getCode().equals(nameType))
            {
                result = displayValue(nameTemp, NULL_DEFAULT_TEXT);
                break;
            }
        }
        if (result == null)
            result = displayValue(null, NULL_DEFAULT_TEXT);
        return result;
    }

    private static String displayName(Name value)
    {
        if (value == null)
        {
            return displayValue(null, NULL_DEFAULT_TEXT);
        }

        String result = CommonNameHelper.formatNameLastNameFirst(value);

        if (StringUtils.isBlank(result))
        {
            return displayValue(null, NULL_DEFAULT_TEXT);
        }

        return result;
    }


    public static String displayPhone(Set value, String phoneType)
    {
        String result = null;
        if (value == null)
            return displayValue(null, NULL_DEFAULT_TEXT);
        Iterator iter = value.iterator();
        while (iter.hasNext())
        {
            Object contactObj = iter.next();
            if (!(contactObj instanceof Phone))
                continue;
            Phone phoneTemp = (Phone)contactObj;
            if (phoneTemp.getType() == null)
                continue;
            if (phoneTemp.getType().getCode().equals(phoneType))
            {
                result = displayValue(phoneTemp, NULL_DEFAULT_TEXT);
                break;
            }
        }
        if (result == null)
            result = displayValue(null, NULL_DEFAULT_TEXT);
        return result;
    }

    public static String displayPhone(Phone value)
    {
        String result = null;
        if (value == null)
            return displayValue(null, NULL_DEFAULT_TEXT);
        result = value.getPhoneNumber();
        return result;
    }

    public static String displayEAddr(Set value, String eAddrType)
    {
        String result = null;
        if (value == null)
            return displayValue(null, NULL_DEFAULT_TEXT);
        Iterator iter = value.iterator();
        while (iter.hasNext())
        {
            Object contactObj = iter.next();
            if (!(contactObj instanceof Email))
                continue;
            Email eAddrTemp = (Email)contactObj;
            if (eAddrTemp.getType() == null)
                continue;
            if (eAddrTemp.getType().getCode().equals(eAddrType))
            {
                result = displayValue(eAddrTemp, NULL_DEFAULT_TEXT);
                break;
            }
        }
        if (result == null)
            result = displayValue(null, NULL_DEFAULT_TEXT);
        return result;
    }

    public static String displayEAddr(Email value)
    {
        String result = null;
        if (value == null)
            return displayValue(null, NULL_DEFAULT_TEXT);
        result = value.getAddress();
        return result;
    }

    public static String displayAddress(Set value, String addrType)
    {
        String result = null;
        if (value == null)
            return displayValue(null, NULL_DEFAULT_TEXT);
        Iterator iter = value.iterator();
        while (iter.hasNext())
        {
            Object contactObj = iter.next();
            if (!(contactObj instanceof Address))
                continue;
            Address addrTemp = (Address)contactObj;
            if (addrTemp.getType() == null)
                continue;
            if (addrTemp.getType().getCode().equals(addrType))
            {
                result = displayValue(addrTemp, NULL_DEFAULT_TEXT);
                break;
            }
        }
        if (result == null)
            result = displayValue(null, NULL_DEFAULT_TEXT);
        return result;
    }

    public static String displayAddress(Address value)
    {
        return displayAddress((SimpleAddress)value);
    }

    /**
     * Returns the formatted Address.
     *
     * @param value The Address to format.
     *
     * @return The formatted Address.
     */
    public static String displayAddress(SimpleAddress value)
    {
        // Return the null value if no address was passed in
        if (value == null)
        {
            return displayValue(null, NULL_DEFAULT_TEXT);
        }

        // Get the formatted value
        String returnValue = value.getFormattedAddress().replaceAll(NEW_LINE, LINE_BREAK);

        // Handle a null result
        if (StringUtils.isEmpty(returnValue))
        {
            return displayValue(null, NULL_DEFAULT_TEXT);
        }

        // Return the formatted result
        return returnValue;
    }

    public static Integer parseInt(String value)
    {
        if (value == null || value.length() == 0)
        {
            return null;
        }

        try
        {
            return Integer.valueOf(value);
        }
        catch (Exception ex)
        {
            return null;
        }
    }

    public static boolean isValidSSN(String value)
    {
        if (value == null || value.length() != 9)
            return false;

        try
        {
            Integer.parseInt(value);
        }
        catch (Exception ex)
        {
            return false;
        }

        return true;
    }

    public static String displaySSN(SSN ssn)
    {
        return (ssn == null) ? NULL_DEFAULT_TEXT : displaySSN(ssn.getSsnText());
    }

    public static String displaySSN(String value)
    {
        StringBuffer result = new StringBuffer();
        if (value == null)
            return displayValue(null, NULL_DEFAULT_TEXT);

        if (!isValidSSN(value))
            return value;

        int idx = 0;
        for (int i = 0; i < value.length(); i++)
        {
            if (idx < 9)
            {
                if (value.charAt(i) != '-')
                {
                    idx++;
                    result.append(value.charAt(i));
                    if (idx == 3 || idx == 5)
                        result.append("-");
                }
            }
        }
        return result.toString();
    }

    private static String displayNamedLookup(NamedLookup value)
    {
        String result = null;
        if (value == null)
            return null;
        result = value.getDescription();
        return result;
    }

    private static String displayCodedDescriptionLookup(Lookup value)
    {
        String result = null;
        if (value == null)
            return null;
        result = value.getDescription();
        return result;
    }
    
    /**
     * Escape certain regular expression characters
     * @param name
     * @return filtered name
     */    
    public static String escapeRegExprChars(String name) {
 	   if (name == null) {
 		   return null;
 	   }
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < name.length(); i++) {
            char curChar = name.charAt(i);
            switch (curChar) {
	            case '\\': 
	            case '/':
	            case ',':
	            case '.':
	            case '+':
	            case '-':
	            case '"':
	            case '@':
	            case '!':
	            case '?':
	            case '<':
	            case '>':
	            case '(':
	            case ')':  
	            case '[':
	            case ']': 
                case '{':
                case '}': 	            	
	            case ';':
	            case ':':
	            case '^':
	            case '$':
	            case '*':
             	   break;
                default:
                    sb.append(curChar);
            }
        }       
        return sb.toString();
    }
}