// Copyright 2000-2020 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.navigation;

import com.intellij.psi.PsiElement;
import com.intellij.util.indexing.*;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.EnumeratorStringDescriptor;
import com.intellij.util.io.KeyDescriptor;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.yaml.YAMLUtil;
import org.jetbrains.yaml.psi.YAMLKeyValue;
import org.jetbrains.yaml.psi.YAMLSequence;
import org.jetbrains.yaml.psi.YamlRecursivePsiElementVisitor;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Map;

public final class YAMLKeysIndex extends FileBasedIndexExtension<String, Integer> {
  @NonNls
  public static final ID<String, Integer> KEY = ID.create("yaml.keys.name");

  @Override
  public int getVersion() {
    return 1;
  }

  @NotNull
  @Override
  public DataIndexer<String, Integer, FileContent> getIndexer() {
    return new DataIndexer<>() {
      @NotNull
      @Override
      public Map<String, Integer> map(@NotNull FileContent inputData) {
        Object2IntMap<String> map = new Object2IntOpenHashMap<>();
        inputData.getPsiFile().accept(new YamlRecursivePsiElementVisitor() {
          @Override
          public void visitKeyValue(@NotNull YAMLKeyValue keyValue) {
            PsiElement key = keyValue.getKey();
            if (key != null) {
              map.put(YAMLUtil.getConfigFullName(keyValue), key.getTextOffset());
            }
            super.visitKeyValue(keyValue);
          }

          @Override
          public void visitSequence(@NotNull YAMLSequence sequence) {
            // Do not visit children
          }
        });
        return map;
      }
    };
  }

  @NotNull
  @Override
  public KeyDescriptor<String> getKeyDescriptor() {
    return EnumeratorStringDescriptor.INSTANCE;
  }

  @NotNull
  @Override
  public DataExternalizer<Integer> getValueExternalizer() {
    return new DataExternalizer<>() {
      @Override
      public void save(@NotNull DataOutput out, Integer value) throws IOException {
        out.writeInt(value);
      }

      @Override
      public Integer read(@NotNull DataInput in) throws IOException {
        return in.readInt();
      }
    };
  }

  @NotNull
  @Override
  public ID<String, Integer> getName() {
    return KEY;
  }

  @NotNull
  @Override
  public FileBasedIndex.InputFilter getInputFilter() {
    return YAMLUtil.YAML_INPUT_FILTER;
  }

  @Override
  public boolean dependsOnFileContent() {
    return true;
  }
}

@@ -293,16 +293,73 @@
 alizer;%0A
+import com.intellij.util.io.EnumeratorIntegerDescriptor;%0A
 import c
@@ -2273,301 +2273,44 @@
 urn 
-new DataExternalizer%3C%3E() %7B%0A      @Override%0A      public void save(@NotNull DataOutput out, Integer value) throws IOException %7B%0A        out.writeInt(value);%0A      %7D%0A%0A      @Override%0A      public Integer read(@NotNull DataInput in) throws IOException %7B%0A        return in.readInt();%0A      %7D%0A    %7D
+EnumeratorIntegerDescriptor.INSTANCE
 ;%0A  

use EnumeratorIntegerDescriptor