import { Remove, Add } from "./index-operation-enum.js";
class IndexRead {
  meta;
  map;
  constructor(meta, map) {
    this.meta = meta;
    this.map = map;
  }
}
class IndexWrite extends IndexRead {
  // Note: does not update self.meta.valueHash (doesn't need to at this point as flush
  // is only called during commit.)
  flush() {
    return this.map.flush();
  }
  clear() {
    return this.map.clear();
  }
}
async function indexValue(lc, index, op, key, val, jsonPointer, allowEmpty) {
  try {
    for (const entry of getIndexKeys(key, val, jsonPointer, allowEmpty)) {
      switch (op) {
        case Add:
          await index.put(entry, val);
          break;
        case Remove:
          await index.del(entry);
          break;
      }
    }
  } catch (e) {
    lc.info?.("Not indexing value", val, ":", e);
  }
}
function getIndexKeys(primary, value, jsonPointer, allowEmpty) {
  const target = evaluateJSONPointer(value, jsonPointer);
  if (target === void 0) {
    if (allowEmpty) {
      return [];
    }
    throw new Error(`No value at path: ${jsonPointer}`);
  }
  const values = Array.isArray(target) ? target : [target];
  const indexKeys = [];
  for (const value2 of values) {
    if (typeof value2 === "string") {
      indexKeys.push(encodeIndexKey([value2, primary]));
    } else {
      throw new Error("Unsupported target type");
    }
  }
  return indexKeys;
}
const KEY_VERSION_0 = "\0";
const KEY_SEPARATOR = "\0";
function encodeIndexKey(indexKey) {
  const secondary = indexKey[0];
  const primary = indexKey[1];
  if (secondary.includes("\0")) {
    throw new Error("Secondary key cannot contain null byte");
  }
  return KEY_VERSION_0 + secondary + KEY_SEPARATOR + primary;
}
function encodeIndexScanKey(secondary, primary) {
  const k = encodeIndexKey([secondary, primary || ""]);
  if (primary === void 0) {
    return k.slice(0, k.length - 1);
  }
  return k;
}
function decodeIndexKey(encodedIndexKey) {
  if (encodedIndexKey[0] !== KEY_VERSION_0) {
    throw new Error("Invalid version");
  }
  const versionLen = KEY_VERSION_0.length;
  const separatorLen = KEY_SEPARATOR.length;
  const separatorOffset = encodedIndexKey.indexOf(KEY_SEPARATOR, versionLen);
  if (separatorOffset === -1) {
    throw new Error("Invalid formatting");
  }
  const secondary = encodedIndexKey.slice(versionLen, separatorOffset);
  const primary = encodedIndexKey.slice(separatorOffset + separatorLen);
  return [secondary, primary];
}
function evaluateJSONPointer(value, pointer) {
  function parseIndex(s) {
    if (s.startsWith("+") || s.startsWith("0") && s.length !== 1) {
      return void 0;
    }
    return parseInt(s, 10);
  }
  if (pointer === "") {
    return value;
  }
  if (!pointer.startsWith("/")) {
    throw new Error(`Invalid JSON pointer: ${pointer}`);
  }
  const tokens = pointer.split("/").slice(1).map((x) => x.replace(/~1/g, "/").replace(/~0/g, "~"));
  let target = value;
  for (const token of tokens) {
    let targetOpt;
    if (Array.isArray(target)) {
      const i = parseIndex(token);
      if (i === void 0) {
        return void 0;
      }
      targetOpt = target[i];
    } else if (target === null) {
      return void 0;
    } else if (typeof target === "object") {
      target = target;
      targetOpt = target[token];
    }
    if (targetOpt === void 0) {
      return void 0;
    }
    target = targetOpt;
  }
  return target;
}
export {
  IndexRead,
  IndexWrite,
  KEY_SEPARATOR,
  KEY_VERSION_0,
  decodeIndexKey,
  encodeIndexKey,
  encodeIndexScanKey,
  evaluateJSONPointer,
  getIndexKeys,
  indexValue
};
//# sourceMappingURL=index.js.map
