import { assert } from "../../../shared/src/asserts.js";
import { stringify } from "../../../shared/src/bigint-json.js";
import { dataTypeToZqlValueType } from "./pg-data-type.js";
function columnType(col, table) {
  const spec = table.columns[col];
  assert(spec, `Unknown column ${col} in table ${table.name}`);
  return spec.dataType;
}
const JSON_STRINGIFIED = "s";
const JSON_PARSED = "p";
function liteRow(row, table, jsonFormat) {
  let copyNeeded = false;
  let numCols = 0;
  for (const key in row) {
    numCols++;
    const val = row[key];
    const liteVal = liteValue(val, columnType(key, table), jsonFormat);
    if (val !== liteVal) {
      copyNeeded = true;
      break;
    }
  }
  if (!copyNeeded) {
    return { row, numCols };
  }
  numCols = 0;
  const converted = {};
  for (const key in row) {
    numCols++;
    converted[key] = liteValue(row[key], columnType(key, table), jsonFormat);
  }
  return { row: converted, numCols };
}
function liteValue(val, pgType, jsonFormat) {
  if (val instanceof Uint8Array || val === null) {
    return val;
  }
  const valueType = liteTypeToZqlValueType(pgType);
  if (valueType === "json") {
    if (jsonFormat === JSON_STRINGIFIED && typeof val === "string") {
      return val;
    }
    return stringify(val);
  }
  const obj = toLiteValue(val);
  return obj && typeof obj === "object" ? stringify(obj) : obj;
}
function toLiteValue(val) {
  switch (typeof val) {
    case "string":
    case "number":
    case "bigint":
      return val;
    case "boolean":
      return val ? 1 : 0;
  }
  if (val === null) {
    return val;
  }
  if (Array.isArray(val)) {
    return val.map((v) => toLiteValue(v));
  }
  assert(
    val.constructor?.name === "Object",
    `Unhandled object type ${val.constructor?.name}`
  );
  return val;
}
function mapLiteDataTypeToZqlSchemaValue(liteDataType) {
  return { type: mapLiteDataTypeToZqlValueType(liteDataType) };
}
function mapLiteDataTypeToZqlValueType(dataType) {
  const type = liteTypeToZqlValueType(dataType);
  if (type === void 0) {
    throw new Error(`Unsupported data type ${dataType}`);
  }
  return type;
}
const TEXT_ENUM_ATTRIBUTE = "|TEXT_ENUM";
const NOT_NULL_ATTRIBUTE = "|NOT_NULL";
const TEXT_ARRAY_ATTRIBUTE = "|TEXT_ARRAY";
function liteTypeString(upstreamDataType2, notNull, textEnum, textArray) {
  let typeString = upstreamDataType2;
  assert(typeString.indexOf("|") === -1, "Upstream type should not contain |");
  if (notNull) {
    typeString += NOT_NULL_ATTRIBUTE;
  }
  if (textEnum) {
    typeString += TEXT_ENUM_ATTRIBUTE;
  }
  if (textArray) {
    typeString += TEXT_ARRAY_ATTRIBUTE;
  }
  return typeString;
}
function upstreamDataType(liteTypeString2) {
  const delim = liteTypeString2.indexOf("|");
  return delim > 0 ? liteTypeString2.substring(0, delim) : liteTypeString2;
}
function nullableUpstream(liteTypeString2) {
  return !liteTypeString2.includes(NOT_NULL_ATTRIBUTE);
}
function liteTypeToZqlValueType(liteTypeString2) {
  return dataTypeToZqlValueType(
    upstreamDataType(liteTypeString2).toLowerCase(),
    liteTypeString2.includes(TEXT_ENUM_ATTRIBUTE),
    isArray(liteTypeString2)
  );
}
function isEnum(liteTypeString2) {
  return liteTypeString2.includes(TEXT_ENUM_ATTRIBUTE);
}
function isArray(liteTypeString2) {
  return liteTypeString2.includes(TEXT_ARRAY_ATTRIBUTE) || // Before we added `|TEXT_ARRAY`, we just used `[]` suffix to indicate arrays.
  liteTypeString2.includes("[]");
}
function assertValidLiteColumnSpec(spec) {
  const { dataType } = spec;
  assert(
    dataType.includes(TEXT_ARRAY_ATTRIBUTE) === dataType.includes("[]"),
    () => `TEXT_ARRAY_ATTRIBUTE and [] must be consistent in dataType: ${dataType}`
  );
  assert(
    dataType.includes("[]") === (spec.elemPgTypeClass !== null),
    () => `[] in dataType (${dataType}) must match elemPgTypeClass presence (${spec.elemPgTypeClass})`
  );
  assert(!/^.+\|.*\[\]/.test(dataType), `Invalid dataType ${dataType}`);
}
export {
  JSON_PARSED,
  JSON_STRINGIFIED,
  TEXT_ARRAY_ATTRIBUTE,
  assertValidLiteColumnSpec,
  isArray,
  isEnum,
  liteRow,
  liteTypeString,
  liteTypeToZqlValueType,
  liteValue,
  mapLiteDataTypeToZqlSchemaValue,
  nullableUpstream,
  upstreamDataType
};
//# sourceMappingURL=lite.js.map
