// Imports
import {terminal} from "./main";
import {variables} from "./modules/variables/variables";
import {operations} from "./modules/operations/operations";
import * as TextEditor from "../visualUI/text_editor";
import * as CodeManagement from "../visualUI/code_generator";
import {SemanticAnalyser} from "../processor/semantic/semanticAnalyser";
import {IVProgProcessor} from "../processor/ivprogProcessor";
import {Modes} from "../processor/modes";
import {LocalizedStrings} from "../services/localizedStringsService";
import {DOMConsole} from "../io/domConsole";
// Imports

// iVProg variables
let proc = null;
let isRunning = false;
let domConsole = new DOMConsole("terminal");

//
const runCodePlayIcon = document.getElementById('runCodePlayIcon');
const runCodeStopIcon = document.getElementById('runCodeStopIcon');

//Debug
const generatedCode = document.getElementById('generatedCode');

function generateCode () {

    console.log(variables);
    console.log(operations);

    let code = `programa {\n`;

    for (let i = 0; i < variables.length; i++) {
        code += `    ${variables[i].type.name} ${variables[i].name} <- ${variables[i].type.barrier}${variables[i].value}${variables[i].type.barrier}\n`;
    }

    code += `    funcao vazio inicio () {\n`;

    for (let i = 0; i < operations.length; i++) {
        code += `        ${operations[i].assignedVariable.name} <- `;

        for (let j = 0; j < operations[i].operators.length; j++) {
            switch (operations[i].operators[j].type.value) {
                case 'VARIABLE':
                    code += operations[i].operators[j].variable.name;
                    break;
                case 'VALUE':
                    code += operations[i].operators[j].value;
                    break;
                case 'OPERATOR':
                    code += operations[i].operators[j].operator.name;
                    break;
            }
        }

        code += `\n`;
    }

    for (let i = 0; i < variables.length; i++) {
        code += `        escreva ("${variables[i].name}: " + ${variables[i].name} + "\\n")\n`;
    }

    code += `    }\n`;

    code += `}`;

    generatedCode.innerText = code;

    return code;
}

export function runCode () {
    if (isRunning) {
        return;
    }
    let strCode = generateCode();

    if (strCode == null) {
        return;
    }

    // toggleConsole(true);

    // if(domConsole == null)
    //   domConsole = new DOMConsole("#ivprog-term");
    //$("#ivprog-term").slideDown(500);
    try {
        const data = SemanticAnalyser.analyseFromSource(strCode);
        proc = new IVProgProcessor(data);
        proc.registerInput(domConsole);
        proc.registerOutput(domConsole);
        $("#ivprog-term").addClass('ivprog-term-active');
        isRunning = true;
        proc.interpretAST().then(_ => {
            scheduleCall(() => {
                if (domConsole.pending_writes.length == 0) {
                    if (proc.mode === Modes.ABORT) {
                        domConsole.info(LocalizedStrings.getMessage("aborted_execution"));
                    } else {
                        domConsole.info(LocalizedStrings.getMessage("success_execution"));
                    }
                    $("#ivprog-term").removeClass('ivprog-term-active');
                    isRunning = false;
                    proc = null;
                    showRunButton();
                    return true;
                }
                return false;
            }, 100);
        }).catch(err => {
            scheduleCall(() => {
                if (domConsole.pending_writes.length == 0) {
                    if (err instanceof Error) {
                        domConsole.err(err.message);
                    } else {
                        domConsole.err(err);
                    }
                    // $("#ivprog-term").removeClass('ivprog-term-active');
                    isRunning = false;
                    proc = null;
                    showRunButton();
                    return true;
                }
                return false;
            }, 100);
        })
    } catch (error) {
        scheduleCall(() => {
            if (domConsole.pending_writes.length == 0) {
                isRunning = false;
                proc = null;
                showRunButton();
                domConsole.err(error.message);
                console.log(error);
                return true;
            }
            return false;
        }, 100);
    }
}

// ***********************************************************************

function scheduleCall (callback, time) {
    const scheduled_call = () => {
        const id = setInterval(() => {
            if (callback()) {
                clearInterval(id);
            }
        }, time)
    }
    scheduled_call();
}

// ***********************************************************************

function showRunButton () {
    runCodePlayIcon.style.display = 'inline';
    runCodeStopIcon.style.display = 'none';
}

function showStopButton () {
    runCodePlayIcon.style.display = 'none';
    runCodeStopIcon.style.display = 'inline';
}

// ***********************************************************************