import { values } from "remeda";
import { logger, logWarnError } from "../logger.js";
export class LikeC4Views {
  constructor(services) {
    this.services = services;
  }
  cache = /* @__PURE__ */ new WeakMap();
  viewsWithReportedErrors = /* @__PURE__ */ new Set();
  get layouter() {
    return this.services.likec4.Layouter;
  }
  async computedViews(cancelToken) {
    const model = await this.services.likec4.ModelBuilder.buildComputedModel(cancelToken);
    return model ? values(model.views) : [];
  }
  async layoutAllViews(cancelToken) {
    const views = await this.computedViews(cancelToken);
    if (views.length === 0) {
      return [];
    }
    const results = [];
    const tasks = [];
    for (const view of views) {
      this.viewsWithReportedErrors.delete(view.id);
      tasks.push(
        this.layouter.layout(view).then((result) => {
          this.cache.set(view, result);
          return result;
        }).catch((e) => {
          this.cache.delete(view);
          logWarnError(e);
          return Promise.reject(e);
        })
      );
    }
    for (const task of await Promise.allSettled(tasks)) {
      if (task.status === "fulfilled") {
        results.push(task.value);
      }
    }
    return results;
  }
  async layoutView(viewId, cancelToken) {
    const model = await this.services.likec4.ModelBuilder.buildComputedModel(cancelToken);
    if (!model) {
      return null;
    }
    const view = model.views[viewId];
    if (!view) {
      return null;
    }
    let cached = this.cache.get(view);
    if (cached) {
      return cached;
    }
    try {
      const result = await this.layouter.layout(view);
      this.viewsWithReportedErrors.delete(viewId);
      this.cache.set(view, result);
      return result;
    } catch (e) {
      if (!this.viewsWithReportedErrors.has(viewId)) {
        const errMessage = e instanceof Error ? e.message : "" + e;
        this.services.shared.lsp.Connection?.window.showErrorMessage(`LikeC4: ${errMessage}`);
        this.viewsWithReportedErrors.add(viewId);
      }
      logger.error(e);
      return Promise.reject(e);
    }
  }
  async diagrams() {
    const layouted = await this.layoutAllViews();
    return layouted.map((l) => l.diagram);
  }
  async viewsAsGraphvizOut() {
    const KEY = "All-LayoutedViews-DotWithSvg";
    const cache = this.services.WorkspaceCache;
    if (cache.has(KEY)) {
      return await Promise.resolve(cache.get(KEY));
    }
    const views = await this.computedViews();
    const tasks = views.map(async (view) => {
      const { dot, svg } = await this.layouter.svg(view);
      return {
        id: view.id,
        dot,
        svg
      };
    });
    const succeed = [];
    const settledResult = await Promise.allSettled(tasks);
    for (const result of settledResult) {
      if (result.status === "fulfilled") {
        succeed.push(result.value);
      } else {
        logWarnError(result.reason);
      }
    }
    cache.set(KEY, succeed);
    return succeed;
  }
  async overviewGraph() {
    const KEY = "OverviewGraph";
    const cache = this.services.WorkspaceCache;
    if (cache.has(KEY)) {
      return await Promise.resolve(cache.get(KEY));
    }
    const views = await this.computedViews();
    const overviewGraph = await this.layouter.layoutOverviewGraph(views);
    cache.set(KEY, overviewGraph);
    return overviewGraph;
  }
}
