"use strict";
(() => {
  // src/decode-history-worker.ts
  var textDecoder = typeof TextDecoder === "function" ? new TextDecoder() : null;
  var HISTORY_GROUP_KEYS = ["ais", "vdes", "aprs", "hf_aprs", "cw", "ft8", "ft4", "ft2", "wspr", "wefax"];
  var workerScope = self;
  function decodeCborUint(view, bytes, state, additional) {
    const offset = state.offset;
    if (additional < 24) return additional;
    if (additional === 24) {
      if (offset + 1 > bytes.length) throw new Error("CBOR payload truncated");
      state.offset += 1;
      return bytes[offset] ?? 0;
    }
    if (additional === 25) {
      if (offset + 2 > bytes.length) throw new Error("CBOR payload truncated");
      state.offset += 2;
      return view.getUint16(offset);
    }
    if (additional === 26) {
      if (offset + 4 > bytes.length) throw new Error("CBOR payload truncated");
      state.offset += 4;
      return view.getUint32(offset);
    }
    if (additional === 27) {
      if (offset + 8 > bytes.length) throw new Error("CBOR payload truncated");
      const value = view.getBigUint64(offset);
      state.offset += 8;
      const numeric = Number(value);
      if (!Number.isSafeInteger(numeric)) throw new Error("CBOR integer exceeds JS safe range");
      return numeric;
    }
    throw new Error("Unsupported CBOR additional info");
  }
  function decodeCborFloat16(bits) {
    const sign = bits & 32768 ? -1 : 1;
    const exponent = bits >> 10 & 31;
    const fraction = bits & 1023;
    if (exponent === 0) {
      return fraction === 0 ? sign * 0 : sign * Math.pow(2, -14) * (fraction / 1024);
    }
    if (exponent === 31) {
      return fraction === 0 ? sign * Infinity : Number.NaN;
    }
    return sign * Math.pow(2, exponent - 15) * (1 + fraction / 1024);
  }
  function decodeCborItem(view, bytes, state) {
    if (state.offset >= bytes.length) throw new Error("CBOR payload truncated");
    const initial = bytes[state.offset++];
    if (initial === void 0) throw new Error("CBOR payload truncated");
    const major = initial >> 5;
    const additional = initial & 31;
    if (major === 0) return decodeCborUint(view, bytes, state, additional);
    if (major === 1) return -1 - decodeCborUint(view, bytes, state, additional);
    if (major === 2) {
      const length = decodeCborUint(view, bytes, state, additional);
      if (state.offset + length > bytes.length) throw new Error("CBOR payload truncated");
      const chunk = bytes.slice(state.offset, state.offset + length);
      state.offset += length;
      return Array.from(chunk);
    }
    if (major === 3) {
      const length = decodeCborUint(view, bytes, state, additional);
      if (state.offset + length > bytes.length) throw new Error("CBOR payload truncated");
      const chunk = bytes.subarray(state.offset, state.offset + length);
      state.offset += length;
      return textDecoder ? textDecoder.decode(chunk) : String.fromCharCode(...chunk);
    }
    if (major === 4) {
      const length = decodeCborUint(view, bytes, state, additional);
      const items = new Array(length);
      for (let i = 0; i < length; i += 1) {
        items[i] = decodeCborItem(view, bytes, state);
      }
      return items;
    }
    if (major === 5) {
      const length = decodeCborUint(view, bytes, state, additional);
      const value = {};
      for (let i = 0; i < length; i += 1) {
        const key = decodeCborItem(view, bytes, state);
        const property = typeof key === "string" || typeof key === "number" || typeof key === "boolean" ? String(key) : JSON.stringify(key);
        value[property] = decodeCborItem(view, bytes, state);
      }
      return value;
    }
    if (major === 6) {
      decodeCborUint(view, bytes, state, additional);
      return decodeCborItem(view, bytes, state);
    }
    if (major === 7) {
      if (additional === 20) return false;
      if (additional === 21) return true;
      if (additional === 22) return null;
      if (additional === 23) return void 0;
      if (additional === 25) {
        if (state.offset + 2 > bytes.length) throw new Error("CBOR payload truncated");
        const bits = view.getUint16(state.offset);
        state.offset += 2;
        return decodeCborFloat16(bits);
      }
      if (additional === 26) {
        if (state.offset + 4 > bytes.length) throw new Error("CBOR payload truncated");
        const value = view.getFloat32(state.offset);
        state.offset += 4;
        return value;
      }
      if (additional === 27) {
        if (state.offset + 8 > bytes.length) throw new Error("CBOR payload truncated");
        const value = view.getFloat64(state.offset);
        state.offset += 8;
        return value;
      }
    }
    throw new Error("Unsupported CBOR major type");
  }
  function decodeCborPayload(buffer) {
    const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
    const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
    const state = { offset: 0 };
    const value = decodeCborItem(view, bytes, state);
    if (state.offset !== bytes.length) {
      throw new Error("Unexpected trailing bytes in decode history payload");
    }
    return value;
  }
  function isHistory(value) {
    return typeof value === "object" && value !== null && !Array.isArray(value);
  }
  async function fetchAndDecodeHistory(url, batchLimit) {
    workerScope.postMessage({ type: "status", phase: "fetching" });
    const resp = await fetch(url, { credentials: "same-origin" });
    if (!resp.ok) throw new Error(`History fetch failed: ${String(resp.status)}`);
    const payload = await resp.arrayBuffer();
    if (payload.byteLength === 0) {
      workerScope.postMessage({ type: "start", total: 0 });
      workerScope.postMessage({ type: "done", total: 0 });
      return;
    }
    workerScope.postMessage({ type: "status", phase: "decoding" });
    const history = decodeCborPayload(payload);
    const total = HISTORY_GROUP_KEYS.reduce((sum, key) => {
      const items = isHistory(history) && Array.isArray(history[key]) ? history[key] : [];
      return sum + items.length;
    }, 0);
    workerScope.postMessage({ type: "start", total });
    let processed = 0;
    const safeLimit = Math.max(1, Math.min(2048, Number(batchLimit) || 512));
    for (const kind of HISTORY_GROUP_KEYS) {
      const items = isHistory(history) && Array.isArray(history[kind]) ? history[kind] : [];
      if (items.length === 0) continue;
      for (let index = 0; index < items.length; index += safeLimit) {
        const messages = items.slice(index, index + safeLimit);
        processed += messages.length;
        workerScope.postMessage({
          type: "group",
          kind,
          messages,
          processed,
          total
        });
      }
    }
    workerScope.postMessage({ type: "done", total });
  }
  function isFetchHistoryRequest(value) {
    return typeof value === "object" && value !== null && "type" in value && value.type === "fetch-history";
  }
  workerScope.onmessage = (event) => {
    const data = event.data;
    if (!isFetchHistoryRequest(data)) return;
    fetchAndDecodeHistory(data.url || "/decode/history", data.batchLimit).catch((error) => {
      workerScope.postMessage({
        type: "error",
        message: error instanceof Error ? error.message : typeof error === "string" ? error : "unknown worker failure"
      });
    });
  };
})();
