<template>
  <div class="machine-state">
    <h3>&#9881; Machine State</h3>

    <div class="section">
      <h4>Registers</h4>
      <div class="registers">
        <div v-for="(reg, idx) in regs" :key="reg"
             class="register" :class="{ changed: changedRegs.has(reg) }"
             :style="{ borderLeftColor: regColors[idx] }">
          <span class="reg-label" :style="{ color: regColors[idx] }">{{ reg }}</span>
          <span class="reg-dec">{{ registers[reg] }}</span>
          <span class="reg-hex">{{ hex(registers[reg]) }}</span>
          <span class="reg-bin">{{ bin(registers[reg]) }}</span>
        </div>
      </div>
    </div>

    <div class="section">
      <h4>Flags</h4>
      <div class="flags-row">
        <div class="flag" :class="{ on: flags.zero }"><span class="led"></span><span>Z</span></div>
        <div class="flag" :class="{ on: flags.carry }"><span class="led"></span><span>C</span></div>
        <div class="flag" :class="{ on: flags.negative }"><span class="led"></span><span>N</span></div>
      </div>
    </div>

    <div v-if="stack && stack.length" class="section">
      <h4>Stack ({{ stack.length }})</h4>
      <div class="stack-list">
        <div v-for="(v, i) in stackRev" :key="i" class="stack-item">{{ v }}</div>
      </div>
    </div>

    <div v-if="showMemory" class="section">
      <h4>Memory</h4>
      <div class="memory-grid">
        <div class="mg-header">
          <span class="mg-corner"></span>
          <span v-for="c in 16" :key="c" class="mg-ch">{{ (c-1).toString(16).toUpperCase() }}</span>
        </div>
        <div v-for="row in memRows" :key="row" class="mg-row">
          <span class="mg-addr">{{ (row*16).toString(16).toUpperCase().padStart(2,'0') }}</span>
          <span v-for="col in 16" :key="col"
                class="mg-cell"
                :class="{ nz: memory[row*16+col-1] !== 0, cg: changedMem.has(row*16+col-1) }">
            {{ memory[row*16+col-1].toString(16).toUpperCase().padStart(2,'0') }}
          </span>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { computed, ref, watch } from 'vue'

const props = defineProps({
  registers: Object, flags: Object, memory: Array, stack: Array,
  showMemory: Boolean, memoryRange: { type: Array, default: () => [0,31] }, changes: Array,
})

const regs = ['R0','R1','R2','R3','R4','R5','R6','R7']
const regColors = ['#06b6d4','#8b5cf6','#f59e0b','#ec4899','#10b981','#3b82f6','#f97316','#ef4444']
const changedRegs = ref(new Set())
const changedMem = ref(new Set())

const stackRev = computed(() => props.stack ? [...props.stack].reverse() : [])
const memRows = computed(() => {
  if (!props.showMemory) return []
  const s = Math.floor((props.memoryRange?.[0]??0)/16)
  const e = Math.floor((props.memoryRange?.[1]??31)/16)
  return Array.from({ length: e-s+1 }, (_,i) => s+i)
})

function hex(v) { return '0x' + (v&0xFFFF).toString(16).toUpperCase().padStart(4,'0') }
function bin(v) {
  const b = (v&0xFFFF).toString(2).padStart(16,'0')
  return b.slice(0,4)+' '+b.slice(4,8)+' '+b.slice(8,12)+' '+b.slice(12)
}

watch(() => props.changes, (ch) => {
  changedRegs.value = new Set(); changedMem.value = new Set()
  if (!ch) return
  for (const c of ch) {
    if (c.type === 'reg') changedRegs.value.add(c.name)
    if (c.type === 'mem') changedMem.value.add(c.addr)
  }
  setTimeout(() => { changedRegs.value = new Set(); changedMem.value = new Set() }, 600)
}, { deep: true })
</script>

<style scoped>
.machine-state {
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: var(--radius-lg); padding: 14px; overflow-y: auto;
}
.machine-state > h3 { font-size: 13px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 1px; margin-bottom: 14px; }
.section { margin-bottom: 16px; }
.section h4 { font-size: 11px; color: var(--text-muted); margin-bottom: 6px; text-transform: uppercase; letter-spacing: 0.5px; }

.registers { display: flex; flex-direction: column; gap: 3px; }
.register {
  display: grid; grid-template-columns: 28px 44px 58px 1fr;
  align-items: center; gap: 4px;
  padding: 4px 6px; background: var(--bg-surface); border-radius: 4px;
  border-left: 3px solid var(--border); transition: background 0.3s;
  font-family: var(--font-mono); font-size: 12px;
}
.register.changed { animation: regfl 0.5s ease; }
@keyframes regfl { 0%,100% { background: var(--bg-surface); } 50% { background: rgba(59,130,246,0.2); } }
.reg-label { font-weight: 700; font-size: 11px; }
.reg-dec { font-weight: 600; text-align: right; font-size: 13px; }
.reg-hex { color: var(--text-muted); font-size: 10px; }
.reg-bin { color: var(--text-muted); font-size: 9px; letter-spacing: 0.5px; }

.flags-row { display: flex; gap: 8px; }
.flag {
  display: flex; align-items: center; gap: 4px;
  padding: 4px 10px; background: var(--bg-surface); border-radius: var(--radius);
  font-family: var(--font-mono); font-weight: 600; font-size: 13px;
}
.led { width: 8px; height: 8px; border-radius: 50%; background: var(--text-muted); transition: all 0.3s; }
.flag.on .led { background: var(--accent-green); box-shadow: 0 0 8px var(--accent-green); }

.stack-list { display: flex; flex-direction: column; gap: 2px; }
.stack-item { font-family: var(--font-mono); padding: 3px 12px; background: var(--bg-surface); border-radius: 4px; font-size: 12px; text-align: center; }

.memory-grid { font-family: var(--font-mono); font-size: 10px; overflow-x: auto; }
.mg-header, .mg-row { display: flex; gap: 1px; }
.mg-header { margin-bottom: 1px; }
.mg-corner { width: 22px; flex-shrink: 0; }
.mg-ch { width: 20px; text-align: center; color: var(--text-muted); }
.mg-addr { width: 22px; flex-shrink: 0; color: var(--text-muted); text-align: right; padding-right: 3px; }
.mg-cell { width: 20px; text-align: center; padding: 2px 0; background: var(--bg-dark); border-radius: 1px; color: var(--text-muted); transition: all 0.3s; }
.mg-cell.nz { color: var(--accent-cyan); background: rgba(6,182,212,0.08); }
.mg-cell.cg { animation: mfl 0.5s ease; }
@keyframes mfl { 0%,100% { background: rgba(6,182,212,0.08); } 50% { background: rgba(6,182,212,0.4); } }
</style>
