// 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 com.jetbrains.python;

import com.intellij.ide.BrowserUtil;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.Annotator;
import com.intellij.notification.NotificationDisplayType;
import com.intellij.notification.NotificationGroup;
import com.intellij.notification.NotificationListener;
import com.intellij.notification.NotificationType;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.FileIndexFacade;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.QualifiedName;
import com.jetbrains.python.psi.PyFile;
import com.jetbrains.python.psi.PyFromImportStatement;
import com.jetbrains.python.psi.PyImportElement;
import com.jetbrains.python.sdk.PythonSdkType;
import org.intellij.lang.annotations.Language;
import org.jetbrains.annotations.NotNull;

/**
 * @author traff
 */
public class PyCharmProfessionalAdvertiser implements Annotator {


  @Language("HTML")
  private static final String NOTIFICATIONS_TEXT =
    "<a href=\"prof\">PyCharm Professional Edition</a> has special support for it.";

  private static final NotificationGroup BALLOON_NOTIFICATIONS = new NotificationGroup("PyCharm Professional Advertiser",
                                                                                       NotificationDisplayType.STICKY_BALLOON, false);
  private static final Key<Boolean> DONT_SHOW_BALLOON = Key.create("showingPyCompatibilityAdvertiserBalloon");

  @Override
  public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {

    if (element instanceof PyFile) {

      final PyFile pyFile = (PyFile)element;
      final Project project = element.getProject();

      if (getSettings(project).shown) {
        return;
      }
      getSettings(project).shown = true;

      final VirtualFile vFile = pyFile.getVirtualFile();
      if (vFile != null && FileIndexFacade.getInstance(project).isInLibraryClasses(vFile)) {
        return;
      }


      if (!moduleUsesPythonSdk(pyFile)) {
        return;
      }

      if (PyCellUtil.hasCells(pyFile)) {
        showInspectionAdvertisement(project, "code cells in the editor");
      }

      if (containsImport(pyFile, "django")) {
        showInspectionAdvertisement(project, "Django Framework");
      }

      if (containsImport(pyFile, "flask")) {
        showInspectionAdvertisement(project, "Flask Framework");
      }

      if (containsImport(pyFile, "pyramid")) {
        showInspectionAdvertisement(project, "Pyramid Framework");
      }
    }
  }

  private static boolean moduleUsesPythonSdk(@NotNull PyFile file) {
    final Module module = ModuleUtilCore.findModuleForFile(file.getVirtualFile(), file.getProject());
    if (module != null) {
      return PythonSdkType.findPythonSdk(module) != null;
    }
    return false;
  }

  private static void showInspectionAdvertisement(@NotNull Project project, @NotNull String message) {
    showSingletonNotification(project, "You are using " + message, NOTIFICATIONS_TEXT, NotificationType.INFORMATION,
                              (notification, event) -> {
                                if ("prof".equals(event.getDescription())) {
                                  BrowserUtil.browse("https://www.jetbrains.com/pycharm/features/editions_comparison_matrix.html");
                                }
                              });
  }

  private static void showSingletonNotification(@NotNull Project project,
                                                @NotNull String title,
                                                @NotNull String htmlContent,
                                                @NotNull NotificationType type,
                                                @NotNull NotificationListener listener) {
    project.putUserData(DONT_SHOW_BALLOON, true);
    BALLOON_NOTIFICATIONS.createNotification(title, htmlContent, type, (notification, event) -> {
      try {
        listener.hyperlinkUpdate(notification, event);
      }
      finally {
        notification.expire();
      }
    }).notify(project);
  }

  private static boolean containsImport(@NotNull PyFile file, String pkg) {
    for (PyFromImportStatement importStatement : file.getFromImports()) {
      final QualifiedName name = importStatement.getImportSourceQName();
      if (name != null && name.toString().toLowerCase().contains(pkg)) {
        return true;
      }
    }
    for (PyImportElement importElement : file.getImportTargets()) {
      final QualifiedName name = importElement.getImportedQName();
      if (name != null && name.toString().toLowerCase().contains(pkg)) {
        return true;
      }
    }
    return false;
  }

  @NotNull
  private static PyCharmProfessionalAdvertiserSettings getSettings(@NotNull Project project) {
    return ServiceManager.getService(project, PyCharmProfessionalAdvertiserSettings.class);
  }
}

@@ -2525,16 +2525,29 @@
  editor%22
+, %22codecells%22
 );%0A     
@@ -2642,16 +2642,20 @@
 oject, %22
+the 
 Django F
@@ -2655,32 +2655,42 @@
 jango Framework%22
+, %22django%22
 );%0A      %7D%0A%0A    
@@ -2776,16 +2776,20 @@
 oject, %22
+the 
 Flask Fr
@@ -2788,32 +2788,41 @@
 Flask Framework%22
+, %22flask%22
 );%0A      %7D%0A%0A    
@@ -2910,16 +2910,20 @@
 oject, %22
+the 
 Pyramid 
@@ -2932,16 +2932,27 @@
 amework%22
+, %22pyramid%22
 );%0A     
@@ -3348,16 +3348,40 @@
  message
+, @NotNull String source
 ) %7B%0A    
@@ -3755,17 +3755,86 @@
 rix.html
-%22
+?utm_source=from_product&utm_medium=advertiser&utm_campaign=%22 + source
 );%0A     

Change wording and add analytics markers to the url