// Ported from js-yaml v3.13.1:
// https://github.com/nodeca/js-yaml/commit/665aadda42349dcae869f12040d9b10ef18d12da
// Copyright 2011-2015 by Vitaly Puzrin. All rights reserved. MIT license.
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
// This module is browser compatible.

import { YAMLError } from "./_error.ts";
import type { KindType, Type } from "./type.ts";
import type { Any, ArrayObject } from "./_utils.ts";

function compileList(
  schema: Schema,
  name: "implicit" | "explicit",
  result: Type[],
): Type[] {
  const exclude: number[] = [];

  for (const includedSchema of schema.include) {
    result = compileList(includedSchema, name, result);
  }

  for (const currentType of schema[name]) {
    for (const [previousIndex, previousType] of result.entries()) {
      if (
        previousType.tag === currentType.tag &&
        previousType.kind === currentType.kind
      ) {
        exclude.push(previousIndex);
      }
    }

    result.push(currentType);
  }

  return result.filter((_type, index): unknown => !exclude.includes(index));
}

export type TypeMap = { [k in KindType | "fallback"]: ArrayObject<Type> };
function compileMap(...typesList: Type[][]): TypeMap {
  const result: TypeMap = {
    fallback: {},
    mapping: {},
    scalar: {},
    sequence: {},
  };

  for (const types of typesList) {
    for (const type of types) {
      if (type.kind !== null) {
        result[type.kind][type.tag] = result["fallback"][type.tag] = type;
      }
    }
  }
  return result;
}

export class Schema implements SchemaDefinition {
  static SCHEMA_DEFAULT?: Schema;

  implicit: Type[];
  explicit: Type[];
  include: Schema[];

  compiledImplicit: Type[];
  compiledExplicit: Type[];
  compiledTypeMap: TypeMap;

  constructor(definition: SchemaDefinition) {
    this.explicit = definition.explicit || [];
    this.implicit = definition.implicit || [];
    this.include = definition.include || [];

    for (const type of this.implicit) {
      if (type.loadKind && type.loadKind !== "scalar") {
        throw new YAMLError(
          "There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.",
        );
      }
    }

    this.compiledImplicit = compileList(this, "implicit", []);
    this.compiledExplicit = compileList(this, "explicit", []);
    this.compiledTypeMap = compileMap(
      this.compiledImplicit,
      this.compiledExplicit,
    );
  }

  /* Returns a new extended schema from current schema */
  extend(definition: SchemaDefinition): Schema {
    return new Schema({
      implicit: [
        ...new Set([...this.implicit, ...(definition?.implicit ?? [])]),
      ],
      explicit: [
        ...new Set([...this.explicit, ...(definition?.explicit ?? [])]),
      ],
      include: [...new Set([...this.include, ...(definition?.include ?? [])])],
    });
  }

  static create() {}
}

export interface SchemaDefinition {
  implicit?: Any[];
  explicit?: Type[];
  include?: Schema[];
}

// denoCacheMetadata={"headers":{"cf-ray":"a223e6586c6b7db6-LAX","age":"1521346","nel":"{\"report_to\":\"cf-nel\",\"success_fraction\":0.0,\"max_age\":604800}","accept-ranges":"bytes","vary":"Origin","alt-svc":"h3=\":443\"; ma=86400","x-jsr-backend":"modules","content-type":"text/typescript","access-control-allow-origin":"*","cache-control":"public, max-age=31536000, immutable","x-robots-tag":"noindex","set-cookie":"__cf_bm=jRsRdCPOND0O21A4jZMrJzCvWgdLs_ypqoD5uG7QT3k-1785241875.2733548-1.0.1.1-JMIUp8ptJ1h1bFPqgtC0eQIEYFDpIk7fb4iZ8nLch15f24lpaLd252ySqKxdtFP3ZxLOclWuRXQ4Xs.7hYHW_aFQ62jv_8TtwOPsavryDF4D5ATd8qHx2onxSRLoDP6K; HttpOnly; SameSite=None; Secure; Path=/; Domain=jsr.io; Expires=Tue, 28 Jul 2026 13:01:15 GMT","server":"cloudflare","x-content-type-options":"nosniff","etag":"\"efe4c8e74972902ed295c41019b1e5e3\"","cross-origin-resource-policy":"cross-origin","date":"Tue, 28 Jul 2026 12:31:15 GMT","content-length":"3015","access-control-expose-headers":"*","cf-cache-status":"HIT","content-security-policy":"default-src 'none'; script-src 'none'; style-src 'none'; img-src 'none'; font-src 'none'; connect-src 'none'; frame-src 'none'; object-src 'none'; frame-ancestors 'none'; sandbox; form-action 'none';","report-to":"{\"group\":\"cf-nel\",\"max_age\":604800,\"endpoints\":[{\"url\":\"https://a.nel.cloudflare.com/report/v4?s=vATijB766303rBWgOFm2hQN8QPdEdHlML18OEVPE49hSDBwFx9rnaFGfDutp6OG%2BARYUmiBM%2BrqBy1uYnsEVc89%2BAcqgLVzcoeHT6Ke1JRQ4i%2BTRwWleqSo%3D\"}]}"},"url":"https://jsr.io/@std/yaml/0.224.3/schema.ts","time":1785241875}