/*******************************************************************************
 * Copyright � 2006 VHA. All rights reserved
 ******************************************************************************/
package gov.va.med.esr.common.model.lookup;

// Java classes
import java.util.Comparator;
import java.io.Serializable;

// Library classes

// Framework classes
import gov.va.med.fw.model.lookup.AbstractCode;
import gov.va.med.fw.model.lookup.AbstractNamedActiveLookup;
import gov.va.med.fw.util.StringUtils;

// ESR classes

/**
 * This class represents a standard report.
 *
 * @author Muddaiah Ranga
 * @author Andrew Pach
 * @version 3.0
 */
public class StandardReport extends AbstractNamedActiveLookup
{
    private static final long serialVersionUID = -6428366598530494875L;

    public static final Code CODE_ACA_1 = new Code("ACA 01");
    public static final Code CODE_ACA_2 = new Code("ACA 02");
    public static final Code CODE_ACA_3 = new Code("ACA 03");
    public static final Code CODE_ACA_4 = new Code("ACA 04");
    public static final Code CODE_ACA_5 = new Code("ACA 05");
    public static final Code CODE_BOS_1 = new Code("BOS 1");
    public static final Code CODE_COR_1 = new Code("COR 1");
    public static final Code CODE_EED_1 = new Code("EED 1");
    public static final Code CODE_EED_2 = new Code("EED 2");
    public static final Code CODE_EED_3 = new Code("EED 3");
    public static final Code CODE_EED_5 = new Code("EED 5");
    public static final Code CODE_EED_6 = new Code("EED 6");
    public static final Code CODE_EED_7 = new Code("EED 7");
    public static final Code CODE_EED_8 = new Code("EED 8");
    public static final Code CODE_EED_9 = new Code("EED 9");
    public static final Code CODE_EED_10 = new Code("EED 10");
    public static final Code CODE_EED_12 = new Code("EED 12");
    public static final Code CODE_IV_1 = new Code("IV 1");
    public static final Code CODE_IV_2 = new Code("IV 2");
    public static final Code CODE_IV_3 = new Code("IV 3");
    public static final Code CODE_IV_4 = new Code("IV 4");
    public static final Code CODE_IV_5 = new Code("IV 5");
    public static final Code CODE_IV_6 = new Code("IV 6");
    public static final Code CODE_IV_7 = new Code("IV 7");
    public static final Code CODE_OPP_1 = new Code("OPP 1");
    public static final Code CODE_OPP_2 = new Code("OPP 2");
    public static final Code CODE_OPP_3 = new Code("OPP 3");
    public static final Code CODE_OPP_4 = new Code("OPP 4");
    public static final Code CODE_OPP_5 = new Code("OPP 5");
    public static final Code CODE_OPP_6 = new Code("OPP 6");
    public static final Code CODE_OPP_7 = new Code("OPP 7");
    public static final Code CODE_QM_3 = new Code("QM 3");
    public static final Code CODE_QM_4 = new Code("QM 4");
    public static final Code CODE_QM_5 = new Code("QM 5");
    public static final Code CODE_QM_6 = new Code("QM 6");
    public static final Code CODE_QM_7 = new Code("QM 7");
    public static final Code CODE_QM_8 = new Code("QM 8");
    public static final Code CODE_QM_9 = new Code("QM 9");
    public static final Code CODE_QM_10 = new Code("QM 10");
    public static final Code CODE_QM_11 = new Code("QM 11");
    public static final Code CODE_QM_12 = new Code("QM 12");
    public static final Code CODE_QM_13 = new Code("QM 13");
    public static final Code CODE_QM_14 = new Code("QM 14");
    public static final Code CODE_QM_15 = new Code("QM 15");
    public static final Code CODE_QM_17 = new Code("QM 17");
    public static final Code CODE_QM_19 = new Code("QM 19");
    public static final Code CODE_QM_20 = new Code("QM 20");
    public static final Code CODE_QM_21 = new Code("QM 21");
    public static final Code CODE_QM_22 = new Code("QM 22");
    public static final Code CODE_QM_23 = new Code("QM 23");
    public static final Code CODE_QM_25 = new Code("QM 25");
    public static final Code CODE_QM_26 = new Code("QM 26");
    public static final Code CODE_QM_27 = new Code("QM 27");
    public static final Code CODE_QM_28 = new Code("QM 28");
    public static final Code CODE_QM_29 = new Code("QM 29");
    public static final Code CODE_QM_30 = new Code("QM 30");
    public static final Code CODE_P8G_3 = new Code("P8G 3");
    public static final Code CODE_P8G_4 = new Code("P8G 4");

    public static final Code CODE_EED_19 = new Code("EED 19");
    public static final Code CODE_EED_20 = new Code("EED 20");
	public static final Code CODE_VOA_01 = new Code("VOA 01");

	public static final Code CODE_CLR_01 = new Code("CLR 01");
	public static final Code CODE_CLR_02 = new Code("CLR 02");


    private ReportType type = null;

    private static Comparator codeComparator = new CodeComparator();

    private static Comparator nameComparator = new StandardReportNameComparator();

    /**
     * Default constructor.
     */
    public StandardReport()
    {
        super();
    }

    public ReportType getType()
    {
        return this.type;
    }

    private void setType(ReportType type)
    {
        this.type = type;
    }

    public String getName()
    {
        return (super.getName() != null && super.getName().length() > 0) ? super.getName() : super.getDescription();
    }

    public String getCodeDescription()
    {
        return this.getDescription() + " (" + this.getCode() + ")";
    }

    public static class Code extends AbstractCode
    {
        private static final long serialVersionUID = 3052407350364389275L;

        private Code(String code)
        {
            super(code);
        }

        public static Code getByCode(String code)
        {
            return (Code)getCode(Code.class, code);
        }
    }

    /**
     * Gets a code comparator that will properly compare standard report codes.
     *
     * @return the code comparator.
     */
    public static Comparator getCodeComparator()
    {
        return codeComparator;
    }

    public static Comparator getNameComparator() {
        return nameComparator;
    }
}

/**
 * A comparator that compares the code portion of the StandardReport (e.g. QM 5).  Note that this comparator will only
 * work on the format of [A-Z]*[0-9]*.
 */
class CodeComparator implements Comparator, Serializable
{
    private static final long serialVersionUID = 4266052596461051197L;

    public int compare(Object object1, Object object2)
    {
        // Get the name from the object
        String code1 = getCode(object1);
        String code2 = getCode(object2);

        // Split the alphabetic and numeric portions of the name into individual buffers.
        StringBuffer code1AlphaBuffer = new StringBuffer();
        StringBuffer code1NumberBuffer = new StringBuffer();
        StringBuffer code2AlphaBuffer = new StringBuffer();
        StringBuffer code2NumberBuffer = new StringBuffer();
        populateAlphaAndNumber(code1, code1AlphaBuffer, code1NumberBuffer);
        populateAlphaAndNumber(code2, code2AlphaBuffer, code2NumberBuffer);

        // Create an integer version of the number buffer
        int number1 = Integer.valueOf(code1NumberBuffer.toString()).intValue();
        int number2 = Integer.valueOf(code2NumberBuffer.toString()).intValue();

        // Perform the comparison of the string portion first
        int compareValue = StringUtils.compareTo(code1AlphaBuffer.toString(), code2AlphaBuffer.toString());

        // If the alphabetic portions are equal, then compare the numeric portion
        if (compareValue == 0)
        {
            if (number1 < number2)
            {
                compareValue = -1;
            }
            else
            {
                if (number1 > number2)
                {
                    compareValue = 1;
                }
                else
                {
                    compareValue = 0;
                }
            }
        }

        // Return the final comparison.
        return compareValue;
    }

    /**
     * Populates the alpha and numberic buffers with the alphabetic and numeric characters in the code string
     * respectively.
     *
     * @param code the code
     * @param alphaBuffer the alphabetic buffer
     * @param numberBuffer the numeric buffer
     */
    private void populateAlphaAndNumber(String code, StringBuffer alphaBuffer, StringBuffer numberBuffer)
    {
        if (code != null)
        {
            for (int i = 0; i < code.length(); i++)
            {
                char ch = code.charAt(i);
                if (Character.isDigit(ch))
                {
                    numberBuffer.append(ch);
                }
                else
                {
                    alphaBuffer.append(ch);
                }
            }
        }
    }

    /**
     * Get the code from the object.
     *
     * @param object the object
     *
     * @return the code.
     */
    private String getCode(Object object)
    {
        String code = null;
        if (object != null)
        {
            if (object instanceof StandardReport)
            {
                code = ((StandardReport)object).getCode();
            }
            else
            {
                code = object.toString();
            }
        }
        return code;
    }
}

class StandardReportNameComparator implements Comparator, Serializable {

    private static final long serialVersionUID = 6562479937547812959L;

        public int compare(Object pObject1, Object pObject2)
        {
            String name1 = (pObject1 != null && pObject1 instanceof StandardReport) ?
                ((StandardReport)pObject1).getDescription() : null;
            String name2 = (pObject2 != null && pObject2 instanceof StandardReport) ?
                ((StandardReport)pObject2).getDescription() : null;
            return (name1 != null && name2 != null) ? name1.compareTo(name2) : 0;
        }
}

