
/*
 * calc.js -- JavaScript calculator
 *
 * Copyright 2009 Michael S. D'Errico -- All rights reserved
 *
 *
 *
 */

var createCalculator = function (display)
{
    var calculated = true;
    var register   = 0;
    var operation  = "";
    var memory     = 0;
    var count      = 0;

    var clear = function ()
    {
        calculated = false;
        register   = 0;
        operation  = "";
    }

    var calc = function (button)
    {
        var temp, i;

        if (display.value.charAt (display.value.length - 1) === 'i')
        {
            display.value = display.value.substring (0, display.value.length - 2);
        }

        var compute = function ()
        {
            switch (operation)
            {
                case '+':   register = Number(register) + Number(display.value); break;
                case '-':   register = Number(register) - Number(display.value); break;
                case '*':   register = Number(register) * Number(display.value); break;
                case '/':   register = Number(register) / Number(display.value); break;
                case 'y^x': register = Math.pow (register, display.value);       break;
                default:    register =                           display.value;  break;
            }

            operation = "";

            display.value = register;
        }

        var computePercent = function ()
        {
            switch (operation)
            {
                case '+':
                case '-':
                {
                    display.value = register * (display.value/100);

                    break;
                }

                case '*':
                {
                    display.value = register * (display.value/100);

                    operation = "";
                    
                    break;
                }

                case '/':
                {
                    display.value = Math.log (register) / Math.log (1 + display.value/100);

                    operation = "";

                    break;
                }

                default:  display.value = display.value/100;  break;
            }
        }

        switch (button)
        {
            case '0':
            {
                if (calculated)
                {
                    display.value = "0";

                    calculated = false;
                }
                else if (display.value !== "0")
                {
                    display.value += "0";
                }

                break;
            }

            case '1': case '2': case '3':
            case '4': case '5': case '6':
            case '7': case '8': case '9':
            {
                if (calculated)
                {
                    display.value = button;

                    calculated = false;
                }
                else if (display.value === "0")
                {
                    display.value = button;
                }
                else
                {
                    display.value += button;
                }

                break;
            }

            case '.':
            {
                if (calculated)
                {
                    display.value = "0.";

                    calculated = false;
                }
                else if (display.value.indexOf ('.') === -1)
                {
                    display.value += ".";
                }

                break;
            }

            case '+/-':
            {
                if (display.value.charAt(0) === '-')
                {
                    display.value = display.value.substring (1);
                }
                else if (display.value.match (/^0(\.0*)?$/) === null)
                {
                    display.value = "-" + display.value;
                }

                break;
            }

            case 'pi':
            {
                display.value = Math.PI;

                calculated = true;

                break;
            }

            case 'e':
            {
                display.value = Math.E;

                calculated = true;

                break;
            }

            case 'inf':
            {
                display.value = Infinity;

                calculated = true;

                break;
            }

            case 'C':
            {
                clear();

                display.value = "0";

                calculated = false;

                break;
            }

            case 'CE':
            {
                display.value = "0";

                calculated = false;

                break;
            }

            case 'del':
            {
                display.value = display.value.substring (0, display.value.length - 1);

                if (display.value.match (/^-0?(\.0*)?$/) !== null)
                {
                    display.value = display.value.substring (1);
                }

                display.value = display.value || "0";

                break;
            }

            case '+': case '-': case '*': case '/':
            {
                compute();

                operation = button;

                calculated = true;

                break;
            }

            case '%':
            {
                computePercent();

                calculated = true;

                break;
            }

            case '=':
            {
                compute();

                calculated = true;

                break;
            }

            case 'swap':
            {
                temp = register;

                register = display.value;

                display.value = temp;

                calculated = true;

                break;
            }

            case 'log':
            {
                display.value = Math.log (display.value);

                calculated = true;

                break;
            }

            case 'log2':
            {
                display.value = Math.LOG2E * Math.log (display.value);

                calculated = true;

                break;
            }

            case 'log10':
            {
                display.value = Math.LOG10E * Math.log (display.value);

                calculated = true;

                break;
            }

            case '2^x':
            {
                display.value = Math.pow (2, display.value);

                calculated = true;

                break;
            }

            case 'e^x':
            {
                display.value = Math.pow (Math.E, display.value);

                calculated = true;

                break;
            }

            case '10^x':
            {
                display.value = Math.pow (10, display.value);

                calculated = true;

                break;
            }

            case 'x^2':
            {
                display.value = Math.pow (display.value, 2);

                calculated = true;

                break;
            }

            case 'x^3':
            {
                display.value = Math.pow (display.value, 3);

                calculated = true;

                break;
            }

            case 'y^x':
            {
                register = display.value;

                operation = 'y^x';

                calculated = true;

                break;
            }

            case 'abs':
            {
                display.value = Math.abs (display.value);

                calculated = true;

                break;
            }

            case 'inv':
            {
                display.value = 1 / display.value;

                calculated = true;

                break;
            }

            case 'fact':
            {
                temp = 1;

                for (i=2; i<=display.value; ++i)
                {
                    temp *= i;

                    if (temp === Infinity)
                    {
                        break;
                    }
                }

                display.value = temp;

                calculated = true;

                break;
            }

            case 'sqrt':
            {
                if (display.value < 0)
                {
                    display.value  = Math.sqrt (-display.value);
                    display.value += " i";
                }
                else
                {
                    display.value = Math.sqrt (display.value);
                }

                calculated = true;

                break;
            }

            case 'root3':
            {
                if (display.value < 0)
                {
                    display.value = - Math.pow (- display.value, 1/3);
                }
                else
                {
                    display.value = Math.pow (display.value, 1/3);
                }

                calculated = true;

                break;
            }

            case 'sin':
            {
                display.value = Math.sin (display.value);

                calculated = true;

                break;
            }

            case 'cos':
            {
                display.value = Math.cos (display.value);

                calculated = true;

                break;
            }

            case 'tan':
            {
                display.value = Math.tan (display.value);

                calculated = true;

                break;
            }

            case 'asin':
            {
                display.value = Math.asin (display.value);

                calculated = true;

                break;
            }

            case 'acos':
            {
                display.value = Math.acos (display.value);

                calculated = true;

                break;
            }

            case 'atan':
            {
                display.value = Math.atan (display.value);

                calculated = true;

                break;
            }

            case 'MC':
            {
                memory = 0;
                count  = 0;

                break;
            }

            case 'MS':
            {
                memory = Number(display.value);
                count  = 1;

                calculated = true;

                break;
            }

            case 'MR':
            {
                display.value = memory;

                calculated = true;

                break;
            }

            case 'M+':
            {
                memory += Number(display.value);
                count  += 1;

                calculated = true;

                break;
            }

            case 'M-':
            {
                memory -= Number(display.value);
                count  += 1;

                calculated = true;

                break;
            }

            case 'MAVG':
            {
                if (count === 0)
                {
                    display.value = 0;
                }
                else
                {
                    display.value = memory / count;
                }

                calculated = true;

                break;
            }
        }

        return false;
    }

    display.value = 0;

    return calc;
}

var draw_radical = function (canvas, root)
{
    if (canvas && canvas.getContext)
    {
        var w = canvas.width;
        var h = canvas.height;

        var context = canvas.getContext ("2d");

        context.save();

        context.clearRect (0, 0, w, h);

        context.strokeStyle = "black";
        context.fillStyle   = "black";
        context.lineCap     = "butt";
        context.lineWidth   = 1;

        context.beginPath();
        context.moveTo   (0,   5*(h-1)/8);
        context.lineTo   (w/8,   (h-1)/2);
        context.lineTo   (w/4,    h-1);
        context.lineTo   (w/2,   (h-1)/8);
        context.lineTo   (w-1,   (h-1)/8);
        context.stroke   ();
        context.closePath();

        var x1 = 7*w/12;
        var x2 = 5*w/6;
        var y1 = (h-1)/2;
        var y2 = 7*(h-1)/8;

        context.beginPath();
        context.moveTo   (x1, y1);
        context.lineTo   (x2, y2);
        context.stroke   ();
        context.closePath();

        context.beginPath();
        context.moveTo   (x1, y2);
        context.lineTo   (x2, y1);
        context.stroke   ();
        context.closePath();

        if (root === 3)
        {
            context.beginPath();
            context.arc      (w/4, h/8,     h/12, 7*Math.PI/6, Math.PI/2,   false);
            context.arc      (w/4, h/8+h/6, h/12, 3*Math.PI/2, 5*Math.PI/6, false);
            context.stroke   ();
            context.closePath();
        }

        context.restore();
    }

    return false;
}


var draw_buttons = function ()
{
    draw_radical (document.getElementById ("sqrt_button"),   2);
    draw_radical (document.getElementById ("root3_button"),  3);
    draw_radical (document.getElementById ("sqrt_button2"),  2);
    draw_radical (document.getElementById ("root3_button2"), 3);

    return false;
}

