// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.yaml.inspections;

import com.intellij.codeInspection.*;
import com.intellij.openapi.project.Project;
import com.intellij.psi.FileViewProvider;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.SmartPointerManager;
import com.intellij.psi.SmartPsiElementPointer;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.yaml.YAMLBundle;
import org.jetbrains.yaml.psi.YAMLKeyValue;
import org.jetbrains.yaml.psi.YAMLMapping;
import org.jetbrains.yaml.psi.YamlPsiElementVisitor;

import java.util.Collection;
import java.util.Map;

public class YAMLDuplicatedKeysInspection extends LocalInspectionTool {
  @NotNull
  @Override
  public final PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
    return new YamlPsiElementVisitor() {
      @Override
      public void visitMapping(@NotNull YAMLMapping mapping) {

        FileViewProvider provider = mapping.getContainingFile().getViewProvider();

        // the check below disables duplicate inspection for template language files
        // because of likely false positives. The example:
        //
        // # data language: YAML
        // # base language: Go Template
        // {{ if .Values.variant1Enabled }}
        // name: variant1   # NOT DUPLICATE!!!
        // {{ else }}
        // name: variant2   # NOT DUPLICATE!!!
        // {{ end }}
        if (provider.getLanguages().size() > 1) {
          return;
        }

        MultiMap<String, YAMLKeyValue> occurrences = new MultiMap<>();

        for (YAMLKeyValue keyValue : mapping.getKeyValues()) {
          final String keyName = keyValue.getKeyText().trim();
          // http://yaml.org/type/merge.html
          if (keyName.equals("<<")) {
            continue;
          }
          if (!keyName.isEmpty()) {
            occurrences.putValue(keyName, keyValue);
          }
        }

        for (Map.Entry<String, Collection<YAMLKeyValue>> entry : occurrences.entrySet()) {
          if (entry.getValue().size() > 1) {
            entry.getValue().forEach((duplicatedKey) -> {
              assert duplicatedKey.getKey() != null;
              assert duplicatedKey.getParentMapping() != null : "This key is get from mapping";

              holder.registerProblem(duplicatedKey.getKey(),
                                     YAMLBundle.message("YAMLDuplicatedKeysInspection.duplicated.key", entry.getKey()),
                                     ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new RemoveDuplicatedKeyQuickFix(duplicatedKey));
            });
          }
        }
      }
    };
  }

  private static class RemoveDuplicatedKeyQuickFix implements LocalQuickFix {
    private final SmartPsiElementPointer<YAMLKeyValue> myKeyValueHolder;

    public RemoveDuplicatedKeyQuickFix(@NotNull final YAMLKeyValue keyValue) {
      myKeyValueHolder = SmartPointerManager.getInstance(keyValue.getProject()).createSmartPsiElementPointer(keyValue);
    }

    @Nls
    @NotNull
    @Override
    public String getFamilyName() {
      return YAMLBundle.message("YAMLDuplicatedKeysInspection.remove.key.quickfix.name");
    }

    @Override
    public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
      YAMLKeyValue keyVal = myKeyValueHolder.getElement();
      if (keyVal == null || keyVal.getParentMapping() == null) {
        return;
      }

      keyVal.getParentMapping().deleteKeyValue(keyVal);
    }
  }
}

@@ -262,50 +262,8 @@
 ct;%0A
-import com.intellij.psi.FileViewProvider;%0A
 impo
@@ -301,16 +301,16 @@
 isitor;%0A
+
 import c
@@ -1071,580 +1071,8 @@
  %7B%0A%0A
-        FileViewProvider provider = mapping.getContainingFile().getViewProvider();%0A%0A        // the check below disables duplicate inspection for template language files%0A        // because of likely false positives. The example:%0A        //%0A        // # data language: YAML%0A        // # base language: Go Template%0A        // %7B%7B if .Values.variant1Enabled %7D%7D%0A        // name: variant1   # NOT DUPLICATE!!!%0A        // %7B%7B else %7D%7D%0A        // name: variant2   # NOT DUPLICATE!!!%0A        // %7B%7B end %7D%7D%0A        if (provider.getLanguages().size() %3E 1) %7B%0A          return;%0A        %7D%0A%0A
     
@@ -1819,18 +1819,21 @@
 key is g
-et
+otten
  from ma

check for multiple languages is removed from YAMLDuplicatedKeyInspection as it's no longer needed; typo