var U = Object.defineProperty;
var r = (n, e) => U(n, "name", { value: e, configurable: !0 });
import { WireType as f, BinaryWriter as O, BinaryReader as V } from "../binary-encoding.js";
import { wrapField as X } from "./field-wrapper.js";
import { scalarZeroValue as h } from "./scalars.js";
import { assert as l } from "./assert.js";
import { isFieldSet as G } from "./reflect.js";
import { ScalarType as o, LongType as I } from "../scalar.js";
import { isMessage as j } from "../is-message.js";
const k = Symbol("@bufbuild/protobuf/unknown-fields"), d = {
  readUnknownFields: !0,
  readerFactory: /* @__PURE__ */ r((n) => new V(n), "readerFactory")
}, N = {
  writeUnknownFields: !0,
  writerFactory: /* @__PURE__ */ r(() => new O(), "writerFactory")
};
function A(n) {
  return n ? Object.assign(Object.assign({}, d), n) : d;
}
r(A, "makeReadOptions");
function M(n) {
  return n ? Object.assign(Object.assign({}, N), n) : N;
}
r(M, "makeWriteOptions");
function J() {
  return {
    makeReadOptions: A,
    makeWriteOptions: M,
    listUnknownFields(n) {
      var e;
      return (e = n[k]) !== null && e !== void 0 ? e : [];
    },
    discardUnknownFields(n) {
      delete n[k];
    },
    writeUnknownFields(n, e) {
      const a = n[k];
      if (a)
        for (const s of a)
          e.tag(s.no, s.wireType).raw(s.data);
    },
    onUnknownField(n, e, t, a) {
      const s = n;
      Array.isArray(s[k]) || (s[k] = []), s[k].push({ no: e, wireType: t, data: a });
    },
    readMessage(n, e, t, a, s) {
      const c = n.getType(), i = s ? e.len : e.pos + t;
      let u, m;
      for (; e.pos < i && ([u, m] = e.tag(), !(s === !0 && m == f.EndGroup)); ) {
        const p = c.fields.find(u);
        if (!p) {
          const w = e.skip(m, u);
          a.readUnknownFields && this.onUnknownField(n, u, m, w);
          continue;
        }
        S(n, e, p, m, a);
      }
      if (s && // eslint-disable-line @typescript-eslint/strict-boolean-expressions
      (m != f.EndGroup || u !== t))
        throw new Error("invalid end group tag");
    },
    readField: S,
    writeMessage(n, e, t) {
      const a = n.getType();
      for (const s of a.fields.byNumber()) {
        if (!G(s, n)) {
          if (s.req)
            throw new Error(`cannot encode field ${a.typeName}.${s.name} to binary: required field not set`);
          continue;
        }
        const c = s.oneof ? n[s.oneof.localName].value : n[s.localName];
        g(s, c, e, t);
      }
      return t.writeUnknownFields && this.writeUnknownFields(n, e), e;
    },
    writeField(n, e, t, a) {
      e !== void 0 && g(n, e, t, a);
    }
  };
}
r(J, "makeBinaryFormat");
function S(n, e, t, a, s) {
  let { repeated: c, localName: i } = t;
  switch (t.oneof && (n = n[t.oneof.localName], n.case != i && delete n.value, n.case = i, i = "value"), t.kind) {
    case "scalar":
    case "enum":
      const u = t.kind == "enum" ? o.INT32 : t.T;
      let m = y;
      if (t.kind == "scalar" && t.L > 0 && (m = K), c) {
        let F = n[i];
        if (a == f.LengthDelimited && u != o.STRING && u != o.BYTES) {
          let L = e.uint32() + e.pos;
          for (; e.pos < L; )
            F.push(m(e, u));
        } else
          F.push(m(e, u));
      } else
        n[i] = m(e, u);
      break;
    case "message":
      const p = t.T;
      c ? n[i].push(T(e, new p(), s, t)) : j(n[i]) ? T(e, n[i], s, t) : (n[i] = T(e, new p(), s, t), p.fieldWrapper && !t.oneof && !t.repeated && (n[i] = p.fieldWrapper.unwrapField(n[i])));
      break;
    case "map":
      let [w, B] = x(t, e, s);
      n[i][w] = B;
      break;
  }
}
r(S, "readField");
function T(n, e, t, a) {
  const s = e.getType().runtime.bin, c = a?.delimited;
  return s.readMessage(
    e,
    n,
    c ? a.no : n.uint32(),
    // eslint-disable-line @typescript-eslint/strict-boolean-expressions
    t,
    c
  ), e;
}
r(T, "readMessageField");
function x(n, e, t) {
  const a = e.uint32(), s = e.pos + a;
  let c, i;
  for (; e.pos < s; ) {
    const [u] = e.tag();
    switch (u) {
      case 1:
        c = y(e, n.K);
        break;
      case 2:
        switch (n.V.kind) {
          case "scalar":
            i = y(e, n.V.T);
            break;
          case "enum":
            i = e.int32();
            break;
          case "message":
            i = T(e, new n.V.T(), t, void 0);
            break;
        }
        break;
    }
  }
  if (c === void 0 && (c = h(n.K, I.BIGINT)), typeof c != "string" && typeof c != "number" && (c = c.toString()), i === void 0)
    switch (n.V.kind) {
      case "scalar":
        i = h(n.V.T, I.BIGINT);
        break;
      case "enum":
        i = n.V.T.values[0].no;
        break;
      case "message":
        i = new n.V.T();
        break;
    }
  return [c, i];
}
r(x, "readMapEntry");
function K(n, e) {
  const t = y(n, e);
  return typeof t == "bigint" ? t.toString() : t;
}
r(K, "readScalarLTString");
function y(n, e) {
  switch (e) {
    case o.STRING:
      return n.string();
    case o.BOOL:
      return n.bool();
    case o.DOUBLE:
      return n.double();
    case o.FLOAT:
      return n.float();
    case o.INT32:
      return n.int32();
    case o.INT64:
      return n.int64();
    case o.UINT64:
      return n.uint64();
    case o.FIXED64:
      return n.fixed64();
    case o.BYTES:
      return n.bytes();
    case o.FIXED32:
      return n.fixed32();
    case o.SFIXED32:
      return n.sfixed32();
    case o.SFIXED64:
      return n.sfixed64();
    case o.SINT64:
      return n.sint64();
    case o.UINT32:
      return n.uint32();
    case o.SINT32:
      return n.sint32();
  }
}
r(y, "readScalar");
function g(n, e, t, a) {
  l(e !== void 0);
  const s = n.repeated;
  switch (n.kind) {
    case "scalar":
    case "enum":
      let c = n.kind == "enum" ? o.INT32 : n.T;
      if (s)
        if (l(Array.isArray(e)), n.packed)
          W(t, c, n.no, e);
        else
          for (const i of e)
            b(t, c, n.no, i);
      else
        b(t, c, n.no, e);
      break;
    case "message":
      if (s) {
        l(Array.isArray(e));
        for (const i of e)
          D(t, a, n, i);
      } else
        D(t, a, n, e);
      break;
    case "map":
      l(typeof e == "object" && e != null);
      for (const [i, u] of Object.entries(e))
        R(t, a, n, i, u);
      break;
  }
}
r(g, "writeField");
function R(n, e, t, a, s) {
  n.tag(t.no, f.LengthDelimited), n.fork();
  let c = a;
  switch (t.K) {
    case o.INT32:
    case o.FIXED32:
    case o.UINT32:
    case o.SFIXED32:
    case o.SINT32:
      c = Number.parseInt(a);
      break;
    case o.BOOL:
      l(a == "true" || a == "false"), c = a == "true";
      break;
  }
  switch (b(n, t.K, 1, c), t.V.kind) {
    case "scalar":
      b(n, t.V.T, 2, s);
      break;
    case "enum":
      b(n, o.INT32, 2, s);
      break;
    case "message":
      l(s !== void 0), n.tag(2, f.LengthDelimited).bytes(s.toBinary(e));
      break;
  }
  n.join();
}
r(R, "writeMapEntry");
function D(n, e, t, a) {
  const s = X(t.T, a);
  t.delimited ? n.tag(t.no, f.StartGroup).raw(s.toBinary(e)).tag(t.no, f.EndGroup) : n.tag(t.no, f.LengthDelimited).bytes(s.toBinary(e));
}
r(D, "writeMessageField");
function b(n, e, t, a) {
  l(a !== void 0);
  let [s, c] = E(e);
  n.tag(t, s)[c](a);
}
r(b, "writeScalar");
function W(n, e, t, a) {
  if (!a.length)
    return;
  n.tag(t, f.LengthDelimited).fork();
  let [, s] = E(e);
  for (let c = 0; c < a.length; c++)
    n[s](a[c]);
  n.join();
}
r(W, "writePacked");
function E(n) {
  let e = f.Varint;
  switch (n) {
    case o.BYTES:
    case o.STRING:
      e = f.LengthDelimited;
      break;
    case o.DOUBLE:
    case o.FIXED64:
    case o.SFIXED64:
      e = f.Bit64;
      break;
    case o.FIXED32:
    case o.SFIXED32:
    case o.FLOAT:
      e = f.Bit32;
      break;
  }
  const t = o[n].toLowerCase();
  return [e, t];
}
r(E, "scalarTypeInfo");
export {
  J as makeBinaryFormat,
  R as writeMapEntry
};
