import * as Effect from "../../Effect.js";
import { flow } from "../../Function.js";
import * as Pipeable from "../../Pipeable.js";
import * as AST from "../../SchemaAST.js";
import * as Parser from "../../SchemaParser.js";
/** @internal */
export const TypeId = "~effect/Schema/Schema";
const SchemaProto = {
  [TypeId]: TypeId,
  pipe() {
    return Pipeable.pipeArguments(this, arguments);
  },
  annotate(annotations) {
    return this.rebuild(AST.annotate(this.ast, annotations));
  },
  annotateKey(annotations) {
    return this.rebuild(AST.annotateKey(this.ast, annotations));
  },
  check(...checks) {
    return this.rebuild(AST.appendChecks(this.ast, checks));
  }
};
/** @internal */
export function make(ast, options) {
  const self = Object.create(SchemaProto);
  if (options) {
    Object.assign(self, options);
  }
  self.ast = ast;
  self.rebuild = ast => make(ast, options);
  self.makeEffect = flow(Parser.makeEffect(self), Effect.mapErrorEager(issue => new SchemaError(issue)));
  self.make = Parser.makeUnsafe(self);
  self.makeOption = Parser.makeOption(self);
  return self;
}
/** @internal */
export const SchemaErrorTypeId = "~effect/Schema/SchemaError";
// not internal
export class SchemaError {
  [SchemaErrorTypeId] = SchemaErrorTypeId;
  _tag = "SchemaError";
  name = "SchemaError";
  issue;
  constructor(issue) {
    this.issue = issue;
  }
  get message() {
    return this.issue.toString();
  }
  toString() {
    return `SchemaError(${this.message})`;
  }
}
/** @internal */
export const jsonReorder = /*#__PURE__*/makeReorder(getJsonPriority);
function getJsonPriority(ast) {
  switch (ast._tag) {
    case "BigInt":
    case "Symbol":
    case "UniqueSymbol":
      return 0;
    default:
      return 1;
  }
}
/** @internal */
export function makeReorder(getPriority) {
  return types => {
    // Create a map of original indices for O(1) lookup
    const indexMap = new Map();
    for (let i = 0; i < types.length; i++) {
      indexMap.set(AST.toEncoded(types[i]), i);
    }
    // Create a sorted copy of the types array
    const sortedTypes = [...types].sort((a, b) => {
      a = AST.toEncoded(a);
      b = AST.toEncoded(b);
      const pa = getPriority(a);
      const pb = getPriority(b);
      if (pa !== pb) return pa - pb;
      // If priorities are equal, maintain original order (stable sort)
      return indexMap.get(a) - indexMap.get(b);
    });
    // Check if order changed by comparing arrays
    const orderChanged = sortedTypes.some((ast, index) => ast !== types[index]);
    if (!orderChanged) return types;
    return sortedTypes;
  };
}
//# sourceMappingURL=schema.js.map