import * as scale from '@pezkuwi/bizinikiwi-bindings';
import { withCache } from './with-cache.mjs';

const _bytes = scale.Bin();
const _buildCodec = (input, cache, stack, _accountId) => {
  if (input.type === "primitive") return scale[input.value];
  if (input.type === "void") return scale._void;
  if (input.type === "AccountId32") return _accountId;
  if (input.type === "AccountId20") return scale.ethAccount;
  if (input.type === "compact")
    return input.isBig ? scale.compactBn : scale.compactNumber;
  if (input.type === "bitSequence") return scale.BitSeq(input.isLSB);
  const buildNextCodec = (nextInput) => buildCodec(nextInput, cache, stack, _accountId);
  const buildVector = (inner2, len) => {
    const innerCodec = buildNextCodec(inner2);
    return len ? scale.Vector(innerCodec, len) : scale.Vector(innerCodec);
  };
  const buildTuple = (value) => scale.Tuple(...value.map(buildNextCodec));
  const buildStruct = (value) => {
    const inner2 = Object.fromEntries(
      Object.entries(value).map(([key, value2]) => [key, buildNextCodec(value2)])
    );
    return scale.Struct(inner2);
  };
  if (input.type === "sequence" && input.value.type === "primitive" && input.value.value === "u8") {
    return _bytes;
  }
  if (input.type === "array") {
    if (input.value.type === "primitive" && input.value.value === "u8")
      return scale.Bin(input.len);
    return buildVector(input.value, input.len);
  }
  if (input.type === "sequence") return buildVector(input.value);
  if (input.type === "tuple") return buildTuple(input.value);
  if (input.type === "struct") return buildStruct(input.value);
  if (input.type === "option") return scale.Option(buildNextCodec(input.value));
  if (input.type === "result")
    return scale.Result(
      buildNextCodec(input.value.ok),
      buildNextCodec(input.value.ko)
    );
  const dependencies = Object.values(input.value).map((v) => {
    switch (v.type) {
      case "void":
        return scale._void;
      case "lookupEntry":
        return buildNextCodec(v.value);
      case "tuple":
        return buildTuple(v.value);
      case "struct":
        return buildStruct(v.value);
      case "array":
        return buildVector(v.value, v.len);
    }
  });
  const inner = Object.fromEntries(
    Object.keys(input.value).map((key, idx) => {
      return [key, dependencies[idx]];
    })
  );
  const indexes = Object.values(input.value).map((x) => x.idx);
  const areIndexesSorted = indexes.every((idx, i) => idx === i);
  const variantCodec = areIndexesSorted ? scale.Variant(inner) : scale.Variant(inner, indexes);
  return input.byteLength ? fixedSizeCodec(variantCodec, input.byteLength) : variantCodec;
};
const buildCodec = withCache(_buildCodec, scale.Self, (res) => res);
const getLookupCodecBuilder = (lookup, accountId = scale.AccountId()) => {
  const cache = /* @__PURE__ */ new Map();
  const buildDefinition = (id) => buildCodec(lookup(id), cache, /* @__PURE__ */ new Set(), accountId);
  return (id) => buildDefinition(id);
};
const fixedSizeCodec = (codec, size) => {
  const allBytes = scale.Bytes(size);
  return scale.createCodec(
    (value) => allBytes.enc(codec.enc(value)),
    (data) => codec.dec(allBytes.dec(data))
  );
};

export { getLookupCodecBuilder };
//# sourceMappingURL=lookup-codec-builder.mjs.map
