import { invariant, nonexhaustive } from "@likec4/core";
import { logger } from "@likec4/log";
import { changeElementStyle } from "./changeElementStyle.js";
import { changeViewLayout } from "./changeViewLayout.js";
import { saveManualLayout } from "./saveManualLayout.js";
export class LikeC4ModelChanges {
  constructor(services) {
    this.services = services;
    this.locator = services.likec4.ModelLocator;
  }
  locator;
  async applyChange(changeView) {
    const lspConnection = this.services.shared.lsp.Connection;
    invariant(lspConnection, "LSP Connection not available");
    let result = null;
    try {
      await this.services.shared.workspace.WorkspaceLock.write(async () => {
        const { doc, edits, modifiedRange } = this.convertToTextEdit(changeView);
        const textDocument = {
          uri: doc.textDocument.uri,
          version: doc.textDocument.version
        };
        if (!edits.length) {
          return;
        }
        const applyResult = await lspConnection.workspace.applyEdit({
          label: `LikeC4 - change view ${changeView.viewId}`,
          edit: {
            changes: {
              [textDocument.uri]: edits
            }
          }
        });
        if (!applyResult.applied) {
          lspConnection.window.showErrorMessage(`Failed to apply changes ${applyResult.failureReason}`);
          return;
        }
        result = {
          uri: textDocument.uri,
          range: modifiedRange
        };
      });
    } catch (e) {
      logger.error(`Failed to apply change ${changeView.change.op} ${changeView.viewId}`, e);
    }
    return result;
  }
  convertToTextEdit({ viewId, change }) {
    const lookup = this.locator.locateViewAst(viewId);
    if (!lookup) {
      throw new Error(`LikeC4ModelChanges: view not found: ${viewId}`);
    }
    switch (change.op) {
      case "change-element-style": {
        return {
          doc: lookup.doc,
          ...changeElementStyle(this.services, {
            ...lookup,
            targets: change.targets,
            style: change.style
          })
        };
      }
      case "change-autolayout": {
        const edit2 = changeViewLayout(this.services, {
          ...lookup,
          layout: change.layout
        });
        return {
          doc: lookup.doc,
          modifiedRange: edit2.range,
          edits: [edit2]
        };
      }
      case "save-manual-layout":
        const edit = saveManualLayout(this.services, {
          ...lookup,
          layout: change.layout
        });
        return {
          doc: lookup.doc,
          modifiedRange: edit.range,
          edits: [edit]
        };
      default:
        nonexhaustive(change);
    }
  }
}
