// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.yaml.inspections;

import com.intellij.codeInspection.*;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiReference;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
import com.intellij.psi.impl.source.codeStyle.CodeEditUtil;
import com.intellij.psi.impl.source.tree.TreeUtil;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiUtilCore;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.yaml.YAMLBundle;
import org.jetbrains.yaml.YAMLElementTypes;
import org.jetbrains.yaml.psi.YAMLAnchor;
import org.jetbrains.yaml.psi.YamlPsiElementVisitor;

import java.util.Collection;

public final class YAMLUnusedAnchorInspection extends LocalInspectionTool {
  @Override
  public @NotNull PsiElementVisitor buildVisitor(final @NotNull ProblemsHolder holder, boolean isOnTheFly) {
    return new YamlPsiElementVisitor() {
      @Override
      public void visitAnchor(@NotNull YAMLAnchor anchor) {
        Collection<PsiReference> references =
          ReferencesSearch.search(anchor, GlobalSearchScope.fileScope(anchor.getContainingFile())).findAll();
        if (references.isEmpty()) {
          holder.registerProblem(
            anchor,
            YAMLBundle.message("inspections.unused.anchor.message", anchor.getName()),
            ProblemHighlightType.LIKE_UNUSED_SYMBOL,
            new RemoveAnchorQuickFix()
          );
        }
      }
    };
  }

  private static class RemoveAnchorQuickFix implements LocalQuickFix {
    @Override
    public @Nls @NotNull String getFamilyName() {
      return YAMLBundle.message("inspections.unused.anchor.quickfix.name");
    }

    @Override
    public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
      YAMLAnchor anchor = (YAMLAnchor)descriptor.getPsiElement();
      if (anchor == null) {
        return;
      }
      PostprocessReformattingAspect.getInstance(project).disablePostprocessFormattingInside(() -> {
        ASTNode node = TreeUtil.prevLeaf(anchor.getNode());
        while (YAMLElementTypes.SPACE_ELEMENTS.contains(PsiUtilCore.getElementType(node))) {
          ASTNode prev = TreeUtil.prevLeaf(node);
          ASTNode parent = node.getTreeParent();
          if (parent != null) {
            CodeEditUtil.removeChild(parent, node);
          }
          node = prev;
        }
        anchor.delete();
      });
    }
  }
}
