<script setup lang="ts">
import "../style.css"
import {inject, Ref, ref} from "vue";
import {Compiler} from "../utils/Complier.ts";
import {Runner, RunnerState} from "../utils/Runner.ts";

let compiler: Compiler = inject("compiler") as Compiler;
let runner: Runner = inject("runner") as Runner;
let machineCode: Ref<string[][], string[][]> = ref([]);
let asmCode: Ref<string[][], string[][]> = ref([]);
let currentPC: Ref<number, number> = ref(-1);
compiler.AddEventListener("CompileFinished", (_) => {
    machineCode.value = Array.from(compiler.PCToMachineCode.values()).map((x) => {
        x = x.slice(2);
        return [x.slice(0, 2), x.slice(2, 4), x.slice(4, 6)];
    });
    asmCode.value = Array.from(compiler.PCToCode.values()).map((x) => {
        return x.split(/[\s,]+/).map((x) => {
            x = x.trim();
            if (compiler.Labels.has(x)) {
                return x + '(' + compiler.Labels.get(x)!.toString(10).padStart(2, '0') + ')';
            }
            return x;
        });
    })
})
runner.AddEventListener("PCChanged", (_) => {
    currentPC.value = runner._processCounter - 1;
})
</script>

<template>
    <div>
        <h2>Machine Code Layout</h2>
        <div id="code-area">
            <div v-for="(instruction,index) in machineCode">
                <div class="code" :class="{currentCode: index === currentPC}">
                    <span class="line-number">{{ index }}</span>
                    <div class="gutter"></div>
                    <span class="mnemonic">{{ instruction[0] }}</span>
                    <span class="operand">{{ instruction[1] }}</span>
                    <span class="operand">{{ instruction[2] }}</span>
                    <div class="split"></div>
                    <span class="asm-mnemonic">{{ asmCode[index][0] }}</span>
                    <span class="asm-operand">{{ asmCode[index][1] }},</span>
                    <span class="asm-operand">{{ asmCode[index][2] }}</span>
                </div>
            </div>
        </div>
    </div>
</template>

<style scoped>
#code-area {
    padding-top: 4px;
    padding-bottom: 4px;
    background-color: #282c34;
    height: 492px;
    overflow-x: auto;
}

.currentCode {
    background-color: #3e4451;
}

.code {
    /*这里的显示需要和 Assembly Code 对齐 但我不知道CodeMirror的行高是怎么算出来的
    反正edge样式中是这个数，但是其他设备很可能会不对齐*/
    height: 28px;
    line-height: 28px;
    display: flex;
}

span {
    display: inline;
    font-family: monospace;
    line-height: 28px;
    overflow-wrap: normal;
    margin: 0;
    font-size: 20px;
}

.line-number {
    padding-right: 3px;
    padding-left: 5px;
    width: 20px;
    text-align: right;
    color: rgb(125, 135, 153);
}

.mnemonic {
    color: rgb(198, 120, 221);
    margin-right: 3px;
}

.operand {
    color: rgb(224, 108, 117);

}

.gutter {
    display: inline;
    width: 9px;
}

.split {
    margin-left: 10px;
    background-color: #9e9e9e;
    width: 1px;
    height: 28px;
}

.asm-mnemonic {
    color: rgb(198, 120, 221);
    margin-left: 10px;
    padding-right: 10px;
    width: 50px;
}

.asm-operand {
    color: rgb(224, 108, 117);
    margin-left: 5px;
    width: 30px;
}
</style>