/*---------------------------------------------------------------------------------------------
 * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
 * See LICENSE.md in the project root for license terms and full copyright notice.
 *--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module AccuDraw
 */
/** @internal */
export var CalculatorOperator;
(function (CalculatorOperator) {
    CalculatorOperator[CalculatorOperator["None"] = 0] = "None";
    CalculatorOperator[CalculatorOperator["Clear"] = 1] = "Clear";
    CalculatorOperator[CalculatorOperator["ClearAll"] = 2] = "ClearAll";
    CalculatorOperator[CalculatorOperator["Backspace"] = 3] = "Backspace";
    CalculatorOperator[CalculatorOperator["Add"] = 4] = "Add";
    CalculatorOperator[CalculatorOperator["Subtract"] = 5] = "Subtract";
    CalculatorOperator[CalculatorOperator["Multiply"] = 6] = "Multiply";
    CalculatorOperator[CalculatorOperator["Divide"] = 7] = "Divide";
    CalculatorOperator[CalculatorOperator["NegPos"] = 8] = "NegPos";
    CalculatorOperator[CalculatorOperator["Decimal"] = 9] = "Decimal";
    CalculatorOperator[CalculatorOperator["Equals"] = 10] = "Equals";
})(CalculatorOperator || (CalculatorOperator = {}));
/** @internal */
export var CalculatorKeyType;
(function (CalculatorKeyType) {
    CalculatorKeyType[CalculatorKeyType["None"] = 0] = "None";
    CalculatorKeyType[CalculatorKeyType["Operator"] = 1] = "Operator";
    CalculatorKeyType[CalculatorKeyType["Equals"] = 2] = "Equals";
})(CalculatorKeyType || (CalculatorKeyType = {}));
/** @internal */
export class CalculatorEngine {
    constructor() {
        this._displayValue = "0";
        this._previousKeyType = CalculatorKeyType.None;
        this._firstValue = "";
        this._modValue = "";
        this._createResultString = (operator, displayedNum) => {
            let resultString = displayedNum;
            if (this._isMathOperator(operator)) {
                const firstValue = this._firstValue;
                const savedOperator = this._operator;
                resultString =
                    firstValue &&
                        savedOperator &&
                        this._previousKeyType !== CalculatorKeyType.Operator &&
                        this._previousKeyType !== CalculatorKeyType.Equals
                        ? this._calculate(firstValue, savedOperator, displayedNum)
                        : displayedNum;
            }
            else {
                switch (operator) {
                    case CalculatorOperator.Clear:
                        resultString = "0";
                        break;
                    case CalculatorOperator.ClearAll:
                        resultString = "0";
                        break;
                    case CalculatorOperator.Backspace:
                        resultString = resultString.slice(0, -1);
                        if (resultString.length === 0)
                            resultString = "0";
                        break;
                    case CalculatorOperator.Decimal:
                        if (!resultString.includes("."))
                            resultString = `${displayedNum}.`;
                        else if (this._previousKeyType === CalculatorKeyType.Operator ||
                            this._previousKeyType === CalculatorKeyType.Equals)
                            resultString = "0.";
                        break;
                    case CalculatorOperator.NegPos:
                        if (displayedNum.length > 0 && displayedNum[0] === "-")
                            resultString = displayedNum.substring(1);
                        else
                            resultString = `-${displayedNum}`;
                        break;
                    case CalculatorOperator.Equals: {
                        const firstValue = this._firstValue;
                        const savedOperator = this._operator;
                        const modValue = this._modValue;
                        if (firstValue && savedOperator) {
                            resultString =
                                this._previousKeyType === CalculatorKeyType.Equals
                                    ? this._calculate(displayedNum, savedOperator, modValue)
                                    : this._calculate(firstValue, savedOperator, displayedNum);
                        }
                        else {
                            resultString = displayedNum;
                        }
                        break;
                    }
                }
            }
            return resultString;
        };
        this._isMathOperator = (operator) => {
            switch (operator) {
                case CalculatorOperator.Add:
                case CalculatorOperator.Subtract:
                case CalculatorOperator.Multiply:
                case CalculatorOperator.Divide:
                    return true;
            }
            return false;
        };
        this._calculate = (n1Str, operator, n2Str) => {
            let result = 0;
            const n1 = parseFloat(n1Str);
            const n2 = parseFloat(n2Str);
            switch (operator) {
                case CalculatorOperator.Add:
                    result = n1 + n2;
                    break;
                case CalculatorOperator.Subtract:
                    result = n1 - n2;
                    break;
                case CalculatorOperator.Multiply:
                    result = n1 * n2;
                    break;
                case CalculatorOperator.Divide:
                    const displayValue = n2;
                    if (displayValue !== 0)
                        result = n1 / displayValue;
                    else
                        result = 0;
                    break;
            }
            return result.toString();
        };
        this._updateCalculatorState = (operator, resultString, displayedNum) => {
            let keyType = CalculatorKeyType.None;
            if (this._isMathOperator(operator)) {
                if (this._firstValue &&
                    this._operator &&
                    this._previousKeyType === CalculatorKeyType.None) {
                    this._firstValue = resultString;
                }
                else {
                    this._firstValue = displayedNum;
                }
                this._operator = operator;
                keyType = CalculatorKeyType.Operator;
            }
            else {
                switch (operator) {
                    case CalculatorOperator.ClearAll:
                        this.clearAll();
                        break;
                    case CalculatorOperator.Equals: {
                        let secondValue = displayedNum;
                        if (this._firstValue) {
                            if (this._previousKeyType === CalculatorKeyType.Equals) {
                                secondValue = this._modValue;
                            }
                        }
                        this._modValue = secondValue;
                        keyType = CalculatorKeyType.Equals;
                    }
                }
            }
            this._previousKeyType = keyType;
        };
        this.clearAll();
    }
    clearAll() {
        this._displayValue = "0";
        this._previousKeyType = CalculatorKeyType.None;
        this._firstValue = "";
        this._modValue = "";
        this._operator = undefined;
    }
    get result() {
        return parseFloat(this._displayValue);
    }
    get displayValue() {
        return this._displayValue;
    }
    processValue(value) {
        let resultString;
        if (this._displayValue === "0" ||
            this._previousKeyType === CalculatorKeyType.Operator ||
            this._previousKeyType === CalculatorKeyType.Equals) {
            resultString = value;
        }
        else {
            resultString = this._displayValue + value;
        }
        this._displayValue = resultString;
        this._previousKeyType = CalculatorKeyType.None;
        return resultString;
    }
    processOperator(operator) {
        const displayedNum = this._displayValue;
        const resultString = this._createResultString(operator, displayedNum);
        this._displayValue = resultString;
        this._updateCalculatorState(operator, resultString, displayedNum);
        return resultString;
    }
}
//# sourceMappingURL=CalculatorEngine.js.map