/*
 * Copyright 2017 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
package io.flutter.project;

import com.intellij.icons.AllIcons;
import com.intellij.ide.IconProvider;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Iconable;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.jetbrains.lang.dart.DartFileType;
import com.jetbrains.lang.dart.psi.DartFile;
import icons.FlutterIcons;
import io.flutter.FlutterUtils;
import io.flutter.pub.PubRoot;
import io.flutter.pub.PubRootCache;
import io.flutter.utils.FlutterModuleUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.util.Objects;

import static com.intellij.psi.impl.ElementBase.overlayIcons;

public class FlutterIconProvider extends IconProvider {

  private static final Icon TEST_FILE = overlayIcons(DartFileType.INSTANCE.getIcon(), AllIcons.Nodes.JunitTestMark);

  @Nullable
  public Icon getIcon(@NotNull final PsiElement element, @Iconable.IconFlags final int flags) {
    final Project project = element.getProject();
    if (!FlutterModuleUtils.declaresFlutter(project)) return null;

    // Directories.
    if (element instanceof PsiDirectory) {
      final VirtualFile dir = ((PsiDirectory)element).getVirtualFile();
      if (!dir.isInLocalFileSystem()) return null;

      final PubRootCache pubRootCache = PubRootCache.getInstance(project);

      // Show an icon for flutter modules.
      final PubRoot pubRoot = pubRootCache.getRoot(dir);
      if (pubRoot != null && dir.equals(pubRoot.getRoot()) && pubRoot.declaresFlutter()) {
        return FlutterIcons.Flutter;
      }

      final PubRoot root = pubRootCache.getRoot(dir.getParent());
      if (root == null) return null;

      // TODO(devoncarew): should we just make the folder a source kind?
      if (dir.equals(root.getLib())) return AllIcons.Modules.SourceRoot;

      if (Objects.equals(dir, root.getAndroidDir())) return AllIcons.Nodes.KeymapTools;
      if (Objects.equals(dir, root.getiOsDir())) return AllIcons.Nodes.KeymapTools;

      if (dir.isDirectory() && dir.getName().equals(".idea")) return AllIcons.Modules.GeneratedFolder;
    }

    // Files.
    if (element instanceof DartFile) {
      final DartFile dartFile = (DartFile)element;
      final VirtualFile file = dartFile.getVirtualFile();
      if (file == null || !file.isInLocalFileSystem()) return null;

      // Use a simple naming convention heuristic to identify test files.
      // TODO(pq): consider pushing up to the Dart Plugin.
      if (FlutterUtils.isInTestDir(dartFile) && file.getName().endsWith("_test.dart")) {
        return TEST_FILE;
      }
    }

    return null;
  }
}

@@ -354,18 +354,28 @@
 Iconable
+.IconFlags
 ;%0A
-
 import c
@@ -485,16 +485,52 @@
 lement;%0A
+import com.intellij.ui.LayeredIcon;%0A
 import c
@@ -920,71 +920,8 @@
 s;%0A%0A
-import static com.intellij.psi.impl.ElementBase.overlayIcons;%0A%0A
 publ
@@ -972,17 +972,16 @@
 vider %7B%0A
-%0A
   privat
@@ -1133,22 +1133,16 @@
 NotNull 
-final 
 PsiEleme
@@ -1162,28 +1162,13 @@
 Icon
-able.IconFlags final
+Flags
  int
@@ -2843,11 +2843,277 @@
 ull;%0A  %7D
+%0A%0A  @NotNull%0A  private static Icon overlayIcons(@NotNull Icon... icons) %7B%0A    final LayeredIcon result = new LayeredIcon(icons.length);%0A%0A    for (int layer = 0; layer %3C icons.length; layer++) %7B%0A      result.setIcon(icons%5Blayer%5D, layer);%0A    %7D%0A%0A    return result;%0A  %7D
 %0A%7D%0A

fix an exception loading the FlutterIconProvider class in EAP (#4942)