import { AstUtils } from "langium";
import { ast } from "../ast.js";
import { RESERVED_WORDS, tryOrLog } from "./_shared.js";
export const specificationRuleChecks = (_) => {
  return tryOrLog((node, accept) => {
    if (node.$containerIndex && node.$containerIndex > 0) {
      accept("warning", `Prefer one specification per document`, {
        node,
        property: "name"
      });
    }
  });
};
export const modelRuleChecks = (_) => {
  return tryOrLog((node, accept) => {
    if (node.$containerIndex && node.$containerIndex > 0) {
      accept("warning", `Prefer one model per document`, {
        node,
        property: "name"
      });
    }
  });
};
export const globalsChecks = (_) => {
  return tryOrLog((node, accept) => {
    if (node.$containerIndex && node.$containerIndex > 0) {
      accept("warning", `Prefer one global block per document`, {
        node,
        property: "name"
      });
    }
  });
};
export const elementKindChecks = (services) => {
  const index = services.shared.workspace.IndexManager;
  return tryOrLog((node, accept) => {
    if (RESERVED_WORDS.includes(node.name)) {
      accept("error", `Reserved word: ${node.name}`, {
        node,
        property: "name"
      });
    }
    const sameKind = index.allElements(ast.ElementKind).filter((n) => n.name === node.name && n.node !== node).head();
    if (sameKind) {
      const isAnotherDoc = sameKind.documentUri !== AstUtils.getDocument(node).uri;
      accept("error", `Duplicate element kind '${node.name}'`, {
        node,
        property: "name",
        ...isAnotherDoc && {
          relatedInformation: [
            {
              location: {
                range: sameKind.nameSegment.range,
                uri: sameKind.documentUri.toString()
              },
              message: `conflicting definition`
            }
          ]
        }
      });
    }
  });
};
export const deploymentNodeKindChecks = (services) => {
  const index = services.shared.workspace.IndexManager;
  return tryOrLog((node, accept) => {
    if (RESERVED_WORDS.includes(node.name)) {
      accept("error", `Reserved word: ${node.name}`, {
        node,
        property: "name"
      });
    }
    const sameKind = index.allElements(ast.DeploymentNodeKind).filter((n) => n.name === node.name && n.node !== node).head();
    if (sameKind) {
      const isAnotherDoc = sameKind.documentUri !== AstUtils.getDocument(node).uri;
      accept("error", `Duplicate deploymentNode kind '${node.name}'`, {
        node,
        property: "name",
        ...isAnotherDoc && {
          relatedInformation: [
            {
              location: {
                range: sameKind.nameSegment.range,
                uri: sameKind.documentUri.toString()
              },
              message: `conflicting definition`
            }
          ]
        }
      });
    }
  });
};
export const tagChecks = (services) => {
  const index = services.shared.workspace.IndexManager;
  return tryOrLog((node, accept) => {
    const tagname = "#" + node.name;
    const sameTag = index.allElements(ast.Tag).filter((n) => n.name === tagname && n.node !== node).head();
    if (sameTag) {
      const isAnotherDoc = sameTag.documentUri !== AstUtils.getDocument(node).uri;
      accept(
        "error",
        `Duplicate tag '${node.name}'`,
        {
          node,
          property: "name",
          ...isAnotherDoc && {
            relatedInformation: [
              {
                location: {
                  range: sameTag.nameSegment.range,
                  uri: sameTag.documentUri.toString()
                },
                message: `conflicting definition`
              }
            ]
          }
        }
      );
    }
  });
};
export const relationshipChecks = (services) => {
  const index = services.shared.workspace.IndexManager;
  return tryOrLog((node, accept) => {
    if (RESERVED_WORDS.includes(node.name)) {
      accept("error", `Reserved word: ${node.name}`, {
        node,
        property: "name"
      });
    }
    const sameKinds = index.allElements(ast.RelationshipKind).filter((n) => n.name === node.name).limit(2).count();
    if (sameKinds > 1) {
      accept("error", `Duplicate RelationshipKind '${node.name}'`, {
        node,
        property: "name"
      });
    }
  });
};
export const globalPredicateChecks = (services) => {
  const index = services.shared.workspace.IndexManager;
  return tryOrLog((node, accept) => {
    const predicateGroups = index.allElements(ast.GlobalPredicateGroup);
    const dynamicPredicateGroups = index.allElements(ast.GlobalDynamicPredicateGroup);
    const sameName = predicateGroups.concat(dynamicPredicateGroups).filter((s) => s.name === node.name).limit(2).count();
    if (sameName > 1) {
      accept("error", `Duplicate GlobalPredicateGroup or GlobalDynamicPredicateGroup name '${node.name}'`, {
        node,
        property: "name"
      });
    }
  });
};
export const globalStyleIdChecks = (services) => {
  const index = services.shared.workspace.IndexManager;
  return tryOrLog((node, accept) => {
    const sameName = index.allElements(ast.GlobalStyleId).filter((s) => s.name === node.name).limit(2).count();
    if (sameName > 1) {
      accept("error", `Duplicate GlobalStyleId name '${node.name}'`, {
        node,
        property: "name"
      });
    }
  });
};
