package com.jetbrains.edu.learning.stepic;

import com.intellij.ide.AppLifecycleListener;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.Ref;
import com.intellij.util.Alarm;
import com.intellij.util.text.DateFormatUtil;
import com.jetbrains.edu.learning.courseGeneration.StudyProjectGenerator;
import org.jetbrains.annotations.NotNull;

import java.util.List;

public class EduStepicUpdater {
  private static final long CHECK_INTERVAL = DateFormatUtil.DAY;

  private final Runnable myCheckRunnable = () -> updateCourseList().doWhenDone(() -> queueNextCheck(CHECK_INTERVAL));
  private final Alarm myCheckForUpdatesAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD);

  public EduStepicUpdater(@NotNull Application application) {
    scheduleCourseListUpdate(application);
  }

  public void scheduleCourseListUpdate(Application application) {
    if (!checkNeeded()) {
      return;
    }
    application.getMessageBus().connect(application).subscribe(AppLifecycleListener.TOPIC, new AppLifecycleListener.Adapter() {
      @Override
      public void appFrameCreated(String[] commandLineArgs, @NotNull Ref<Boolean> willOpenProject) {

        long timeToNextCheck = StepicUpdateSettings.getInstance().getLastTimeChecked() + CHECK_INTERVAL - System.currentTimeMillis();
        if (timeToNextCheck <= 0) {
          myCheckRunnable.run();
        }
        else {
          queueNextCheck(timeToNextCheck);
        }
      }
    });
  }

  private static ActionCallback updateCourseList() {
    ActionCallback callback = new ActionCallback();
    ApplicationManager.getApplication().executeOnPooledThread(() -> {
      final List<CourseInfo> courses = EduStepicConnector.getCourses();
      StudyProjectGenerator.flushCache(courses);
      StepicUpdateSettings.getInstance().setLastTimeChecked(System.currentTimeMillis());
    });
    return callback;
  }

  private void queueNextCheck(long interval) {
    myCheckForUpdatesAlarm.addRequest(myCheckRunnable, interval);
  }

  private static boolean checkNeeded() {
    final List<CourseInfo> courses = StudyProjectGenerator.getCoursesFromCache();
    long timeToNextCheck = StepicUpdateSettings.getInstance().getLastTimeChecked() + CHECK_INTERVAL - System.currentTimeMillis();
    return courses.isEmpty() || timeToNextCheck <= 0;
  }
}

@@ -79,24 +79,122 @@
 leListener;%0A
+import com.intellij.notification.Notification;%0Aimport com.intellij.notification.NotificationType;%0A
 import com.i
@@ -381,16 +381,66 @@
 il.Ref;%0A
+import com.intellij.openapi.util.text.StringUtil;%0A
 import c
@@ -1970,24 +1970,114 @@
 tCourses();%0A
+      final List%3CCourseInfo%3E cachedCourses = StudyProjectGenerator.getCoursesFromCache();%0A
       StudyP
@@ -2201,16 +2201,594 @@
 llis());
+%0A%0A      courses.removeAll(cachedCourses);%0A      if (!courses.isEmpty()) %7B%0A        final String message;%0A        final String title;%0A        if (courses.size() == 1) %7B%0A          message = courses.get(0).getName();%0A          title = %22New course available%22;%0A        %7D%0A        else %7B%0A          title = %22New courses available%22;%0A          message = StringUtil.join(courses, CourseInfo::getName, %22, %22);%0A        %7D%0A        final Notification notification =%0A          new Notification(%22New.course%22, title, message, NotificationType.INFORMATION);%0A        notification.notify(null);%0A      %7D
 %0A    %7D);

add notification about new course availability