import { invariant } from "@likec4/core";
import { DocumentCache, DocumentState } from "langium";
import { pipe } from "remeda";
import { isFqnIndexedDocument } from "../ast.js";
import { BaseParser } from "./parser/Base.js";
import { DeploymentModelParser } from "./parser/DeploymentModelParser.js";
import { DeploymentViewParser } from "./parser/DeploymentViewParser.js";
import { ExpressionV2Parser } from "./parser/FqnRefParser.js";
import { GlobalsParser } from "./parser/GlobalsParser.js";
import { ModelParser } from "./parser/ModelParser.js";
import { PredicatesParser } from "./parser/PredicatesParser.js";
import { SpecificationParser } from "./parser/SpecificationParser.js";
import { ViewsParser } from "./parser/ViewsParser.js";
const DocumentParserFromMixins = pipe(
  BaseParser,
  ExpressionV2Parser,
  ModelParser,
  DeploymentModelParser,
  DeploymentViewParser,
  PredicatesParser,
  SpecificationParser,
  ViewsParser,
  GlobalsParser
);
export class DocumentParser extends DocumentParserFromMixins {
}
export class LikeC4ModelParser {
  constructor(services) {
    this.services = services;
    this.cachedParsers = new DocumentCache(services.shared, DocumentState.Validated);
  }
  cachedParsers;
  parse(doc) {
    invariant(isFqnIndexedDocument(doc), `Not a FqnIndexedDocument: ${doc.uri.toString(true)}`);
    try {
      const props = {
        c4Specification: {
          tags: /* @__PURE__ */ new Set(),
          elements: {},
          relationships: {},
          colors: {},
          deployments: {}
        },
        c4Elements: [],
        c4Relations: [],
        c4Deployments: [],
        c4DeploymentRelations: [],
        c4Globals: {
          predicates: {},
          dynamicPredicates: {},
          styles: {}
        },
        c4Views: []
      };
      doc = Object.assign(doc, props);
      const parser = this.forDocument(doc);
      parser.parseSpecification();
      parser.parseModel();
      parser.parseGlobals();
      parser.parseDeployment();
      parser.parseViews();
      return parser.doc;
    } catch (cause) {
      throw new Error(`Error parsing document ${doc.uri.toString()}`, { cause });
    }
  }
  forDocument(doc) {
    invariant(isFqnIndexedDocument(doc), `Not a FqnIndexedDocument: ${doc.uri.toString(true)}`);
    return this.cachedParsers.get(
      doc.uri,
      "DocumentParser",
      () => new DocumentParser(this.services, doc)
    );
  }
}
