package com.jetbrains.edu.learning.stepic;
import com.intellij.ide.AppLifecycleListener;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationType;
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.openapi.util.text.StringUtil;
import com.intellij.util.Alarm;
import com.intellij.util.text.DateFormatUtil;
import com.jetbrains.edu.learning.StudySettings;
import com.jetbrains.edu.learning.courseFormat.Course;
import com.jetbrains.edu.learning.courseFormat.RemoteCourse;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Date;
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() {
@Override
public void appFrameCreated(String[] commandLineArgs, @NotNull Ref<Boolean> willOpenProject) {
long timeToNextCheck = StudySettings.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<Course> courses = EduStepicConnector.getCourses(null);
StudySettings.getInstance().setLastTimeChecked(System.currentTimeMillis());
if (!courses.isEmpty()) {
List<Course> updated = new ArrayList<>();
for (Course course : courses) {
if (course instanceof RemoteCourse && ((RemoteCourse)course).getUpdateDate().
after(new Date(StudySettings.getInstance().getLastTimeChecked()))) {
updated.add(course);
}
}
if (updated.isEmpty()) return;
final String message;
final String title;
if (updated.size() == 1) {
message = updated.get(0).getName();
title = "New course available";
}
else {
title = "New courses available";
message = StringUtil.join(updated, Course::getName, ", ");
}
final Notification notification = new Notification("New.course", title, message, NotificationType.INFORMATION);
notification.notify(null);
}
});
return callback;
}
private void queueNextCheck(long interval) {
myCheckForUpdatesAlarm.addRequest(myCheckRunnable, interval);
}
private static boolean checkNeeded() {
long timeToNextCheck = StudySettings.getInstance().getLastTimeChecked() + CHECK_INTERVAL - System.currentTimeMillis();
return timeToNextCheck <= 0;
}
}