// Calculator block
// API -- the calculator module exports the following functions
//
// setConfig               -- HTML file using this module calls this to set the path of the config file
// setMaximumDecimalPlaces -- Result will be rounded to this number of decimal places; call to change the default of 3
// setResultCallback       -- If this is set, calculator will call the callback function every time an expression is evaluated
// getResult               -- This will return an object of form {resultAvailable, valueText}
//                            resultAvailable: true if a valid result is available
//                            valueText: if resultAvailable is true, this contains a string with the displayed result

import $ from "./jquery.module.js";
import SetConfig from "./set_config_class.js";

let config;
let decimalPlaces = 3;
let resultCallback = null;
let answer = {
    resultAvailable: false,
    valueText: "",
};
const calculatorHTML = `
                    <div id="calc">
                        <div class="calculator">
                            <div class="display">
                                <div id="pendingOperationScreen"></div>
                                <div id="currentOperationScreen">0</div>
                            </div>
                            <div class="buttons">
                                <button class="btn" id="clear">AC</button>
                                <button class="btn" id="backspace">C</button>
                                <button class="btn" data-operation="/">/</button>
                                <button class="btn" data-operation="*">*</button>
                                <button class="btn" data-number="7">7</button>
                                <button class="btn" data-number="8">8</button>
                                <button class="btn" data-number="9">9</button>
                                <button class="btn" data-operation="-">-</button>
                                <button class="btn" data-number="4">4</button>
                                <button class="btn" data-number="5">5</button>
                                <button class="btn" data-number="6">6</button>
                                <button class="btn" data-operation="+">+</button>
                                <button class="btn" data-number="1">1</button>
                                <button class="btn" data-number="2">2</button>
                                <button class="btn" data-number="3">3</button>
                                <button class="btn" data-number="0">0</button>
                                <button class="btn" data-number=".">.</button>
                                <button class="btn" id="equals">=</button>
                            </div>
                        </div>
                    </div>
`;

let setConfigHandler = new SetConfig();

function setConfig(config) {
    setConfigHandler.setConfig(config);
}

function setMaximumDecimalPlaces(maxPlaces) {
    decimalPlaces = maxPlaces;
}

function setResultCallback(callback) {
    resultCallback = callback;
}

function getResult() {
    return answer;
}

function insertCalculatorAt(parentDiv) {
    $(`#${parentDiv}`).html(calculatorHTML);
}

$( document ).ready(async function() {
    config = await setConfigHandler.getConfigAsync();

    insertCalculatorAt(config.options.calculatorDiv);

// Get references to the display elements and buttons
    const pendingOperationScreen = document.getElementById('pendingOperationScreen');
    const currentOperationScreen = document.getElementById('currentOperationScreen');
    const buttons = document.querySelectorAll('.btn');

    let currentOperation = ''; // Stores the current operation (+, -, *, /)
    let lastOperation = ''; // Stores the last operation value
    let shouldResetScreen = false; // Flag to reset the screen for new input
    let justEvaluated = false; // Flag to check if the last action was an evaluation


// Add event listeners to all buttons
    buttons.forEach(button => {
        button.addEventListener('click', () => {
            if (button.dataset.number) {
                appendNumber(button.dataset.number); // Handle number button click
            } else if (button.dataset.operation) {
                chooseOperation(button.dataset.operation); // Handle operation button click
            } else if (button.id === 'equals') {
                evaluate(); // Handle equals button click
            } else if (button.id === 'clear') {
                clear(); // Handle clear button click
            } else if (button.id === 'backspace') {
                deleteLast(); // Handle backspace button click
            }
        });
    });

// Function to append a number to the current operation screen
    function appendNumber(number) {
        if (shouldResetScreen || justEvaluated) {
            resetScreen(); // Reset the screen if needed
            justEvaluated = false;
        }
        if (currentOperationScreen.innerText === '0' || currentOperationScreen.innerText === '') {
            currentOperationScreen.innerText = number; // Set the screen to the clicked number
        } else {
            currentOperationScreen.innerText += number; // Append the clicked number
        }
    }

// Function to choose an operation (+, -, *, /)
    function chooseOperation(operation) {
        if (currentOperation !== '') evaluate(); // Evaluate the current operation if any
        lastOperation = currentOperationScreen.innerText; // Store the current screen value as the last operation
        currentOperation = operation; // Set the current operation
        if (config.options?.showPendingOperation) {
            pendingOperationScreen.innerText = operation;
        }
        shouldResetScreen = true; // Set the flag to reset the screen for new input
        justEvaluated = false; // Reset the evaluation flag
        answer = {resultAvailable: false, valueText: ""};
    }

// Function to evaluate the current operation
    function evaluate() {
        if (currentOperation === '' || shouldResetScreen) return; // Return if no operation is set or screen needs reset
        let result;
        const last = parseFloat(lastOperation); // Parse the last operation value
        const current = parseFloat(currentOperationScreen.innerText); // Parse the current screen value
        switch (currentOperation) {
            case '+':
                result = last + current;
                break;
            case '-':
                result = last - current;
                break;
            case '*':
                result = last * current;
                break;
            case '/':
                result = last / current;
                break;
            default:
                return;
        }
        const valueText = parseFloat(result.toFixed(decimalPlaces));
        currentOperationScreen.innerText = valueText; // Display the result
        pendingOperationScreen.innerText = ''; // Clear the last operation screen
        currentOperation = ''; // Reset the current operation
        justEvaluated = true; // Set the evaluation flag
        answer = {resultAvailable: true, valueText};
        if (resultCallback) {
            resultCallback(valueText);
        }
    }

// Function to clear the calculator screen and reset all values
    function clear() {
        currentOperationScreen.innerText = '0'; // Reset the current screen to 0
        pendingOperationScreen.innerText = ''; // Clear the last operation screen
        currentOperation = ''; // Reset the current operation
        lastOperation = ''; // Reset the last operation
        justEvaluated = false; // Reset the evaluation flag
        answer = {resultAvailable: false, valueText: ""};
    }

// Function to delete the last digit from the current screen
    function deleteLast() {
        currentOperationScreen.innerText = currentOperationScreen.innerText.slice(0, -1); // Remove the last character
        if (currentOperationScreen.innerText === '') {
            currentOperationScreen.innerText = '0'; // Reset to 0 if the screen is empty
        }
    }

// Function to reset the screen for new input
    function resetScreen() {
        currentOperationScreen.innerText = ''; // Clear the current screen
        shouldResetScreen = false; // Reset the screen reset flag
    }
});

export {setConfig, setMaximumDecimalPlaces, setResultCallback, getResult};