/*
 * Calculator.java  $Revision: 1.8 $  $Date: 2007/04/16 05:14:26 $
 *
 * Copyright (c) Meldcraft, Inc. 2006
 */
package com.meldcraft.calculator;

/**
 * @version $Revision: 1.8 $ $Date: 2007/04/16 05:14:26 $
 * @author Rob Richards
 */
public class Calculator
{
    /**
     * Issues command and returns the display text.  The command
     * is any key on the calculator.
     * 
     * @param command
     * @return
     */
    public synchronized String calculate(String command)
    {
        String ret = null;

        boolean handled = false;
        String pre = "calc.";
        if (command.startsWith(pre) && (command.length() > pre.length()))
        {
            if (doCalculate(command.substring(pre.length())))
            {
                handled = true;
                ret = text;
            }
        }

        if (!handled)
        {
            throw new RuntimeException("Unknown command: " + command);
        }

        return ret;
    }

    /*
     * Calculator implementation based on http://www.yamaza.com/java/Calc.java,
     * http://www.geocities.com/entity05/java/myjava.html
     */
    private double dReg1;
    private double dReg2;
    private String sOperator;
    private String text = "0";
    private boolean isFixReg = true;
    private String sText2;
    private String sText1;
    private double dMem;

    private boolean doCalculate(String arg)
    {
        boolean ret = true;

        //
        // numeric key input
        //
        if ("c".equals(arg))
        {
            dReg1 = 0.0d;
            dReg2 = 0.0d;
            sOperator = "";
            text = "0";
            isFixReg = true;
        }
        else if (("0".equals(arg)) | ("1".equals(arg)) | ("2".equals(arg))
               | ("3".equals(arg)) | ("4".equals(arg)) | ("5".equals(arg))
               | ("6".equals(arg)) | ("7".equals(arg)) | ("8".equals(arg))
               | ("9".equals(arg)) | (".".equals(arg)))
        {
            if (isFixReg)
                sText2 = (String) arg;
            else
            {
                if (!".".equals(arg) || sText2.indexOf(".") == -1)
                    sText2 = text + arg;
            }
            text = sText2;
            isFixReg = false;
        }
        //
        // operations
        //
        else if (("+".equals(arg)) | ("-".equals(arg))
               | ("\u00d7".equals(arg)) | ("\u00f7".equals(arg)) | ("=".equals(arg)))
        {
            sText1 = text;
            dReg2 = (Double.valueOf(sText1)).doubleValue();
            dReg1 = calcValue(sOperator, dReg1, dReg2);
            Double dTemp = new Double(dReg1);
            sText2 = dTemp.toString();
            text = sText2;
            sOperator = (String) arg;
            isFixReg = true;
        }
        //
        // memory clear operation
        //
        else if ("mc".equals(arg))
        {
            dMem = 0;
        }
        //
        // memory read operation
        //
        else if ("mr".equals(arg))
        {
            Double dTemp = new Double(dMem);
            sText2 = dTemp.toString();
            text = sText2;
            sOperator = "";
            isFixReg = true;
        }
        //
        // memory add operation
        //
        else if ("m+".equals(arg))
        {
            sText1 = text;
            dReg2 = (Double.valueOf(sText1)).doubleValue();
            dReg1 = calcValue(sOperator, dReg1, dReg2);
            Double dTemp = new Double(dReg1);
            sText2 = dTemp.toString();
            text = sText2;
            dMem = dMem + dReg1;
            sOperator = "";
            isFixReg = true;
        }
        //
        // memory sub operation
        //
        else if ("m-".equals(arg))
        {
            sText1 = text;
            dReg2 = (Double.valueOf(sText1)).doubleValue();
            dReg1 = calcValue(sOperator, dReg1, dReg2);
            Double dTemp = new Double(dReg1);
            sText2 = dTemp.toString();
            text = sText2;
            dMem = dMem - dReg1;
            sOperator = "";
            isFixReg = true;
        }
        else
        {
            ret = false;
        }

        return ret;
    }

    //-------------
    // Calculation
    //-------------
    private double calcValue(String sOperator, double dReg1, double dReg2)
    {
        if ("+".equals(sOperator)) dReg1 = dReg1 + dReg2;
        else if ("-".equals(sOperator)) dReg1 = dReg1 - dReg2;
        else if ("\u00d7".equals(sOperator)) dReg1 = dReg1 * dReg2;
        else if ("\u00f7".equals(sOperator)) dReg1 = dReg1 / dReg2;
        else dReg1 = dReg2;
        return dReg1;
    }
}



