let port = null;
let reader = null;
let writer = null;

export function isConnected() {
  return port !== null;
}

export function getWriter() {
  return writer;
}

export async function connect(baudRate = 115200) {
  if (port) return port;
  port = await navigator.serial.requestPort();
  await port.open({ baudRate });

  const textDecoder = new TextDecoderStream();
  const textEncoder = new TextEncoderStream();

  port.readable.pipeTo(textDecoder.writable);
  textEncoder.readable.pipeTo(port.writable);

  reader = textDecoder.readable.getReader();
  writer = textEncoder.writable.getWriter();

  readLoop();
  return port;
}

export async function disconnect() {
  if (reader) {
    try { await reader.cancel(); } catch (_) { /* already closed */ }
    reader = null;
  }
  if (writer) {
    try { await writer.close(); } catch (_) { /* already closed */ }
    writer = null;
  }
  if (port) {
    try { await port.close(); } catch (_) { /* already closed */ }
    port = null;
  }
}

export async function writeString(str) {
  if (writer) await writer.write(str);
}

const listeners = new Set();

export function onData(callback) {
  listeners.add(callback);
  return () => listeners.delete(callback);
}

async function readLoop() {
  try {
    while (reader) {
      const { value, done } = await reader.read();
      if (done) break;
      if (value) {
        for (const cb of listeners) cb(value);
      }
    }
  } catch (_) {
    /* port disconnected */
  }
}
