package com.screenshot.scheduler;
import com.cronutils.model.Cron;
import com.cronutils.model.CronType;
import com.cronutils.model.definition.CronDefinitionBuilder;
import com.cronutils.model.time.ExecutionTime;
import com.cronutils.parser.CronParser;
import com.screenshot.config.AppConfig;
import com.screenshot.service.ScreenshotService;
import java.time.Duration;
import java.time.ZonedDateTime;
import java.util.Optional;
import java.util.concurrent.*;
public class ScreenshotScheduler {
private final ScheduledExecutorService scheduler;
private final ScreenshotService screenshotService;
private final AppConfig config;
private ScheduledFuture<?> currentTask;
private volatile boolean running = false;
public ScreenshotScheduler(ScreenshotService screenshotService, AppConfig config) {
this.scheduler = Executors.newScheduledThreadPool(1);
this.screenshotService = screenshotService;
this.config = config;
}
/**
* Запустить планировщик
*/
public void start() {
if (running) {
System.out.println("Планировщик уже запущен");
return;
}
running = true;
if (config.useCron()) {
startWithCron();
} else {
startWithInterval();
}
System.out.println("Планировщик запущен");
}
/**
* Запуск с использованием интервала
*/
private void startWithInterval() {
int intervalMinutes = config.getIntervalMinutes();
currentTask = scheduler.scheduleAtFixedRate(
this::takeScreenshot,
0, // Начать сразу
intervalMinutes,
TimeUnit.MINUTES
);
System.out.println("Скриншоты каждые " + intervalMinutes + " мин.");
}
/**
* Запуск с использованием cron-выражения
*/
private void startWithCron() {
String cronExpression = config.getCronExpression();
CronParser parser = new CronParser(
CronDefinitionBuilder.instanceDefinitionFor(CronType.SPRING)
);
try {
Cron cron = parser.parse(cronExpression);
ExecutionTime executionTime = ExecutionTime.forCron(cron);
scheduleCronTask(executionTime);
System.out.println("Cron расписание: " + cronExpression);
} catch (IllegalArgumentException e) {
System.err.println("Неверное cron-выражение: " + cronExpression);
System.out.println("Используем интервал по умолчанию");
startWithInterval();
}
}
/**
* Рекурсивное планирование задач по cron
*/
private void scheduleCronTask(ExecutionTime executionTime) {
if (!running) return;
ZonedDateTime now = ZonedDateTime.now();
Optional<Duration> nextExecution = executionTime.timeToNextExecution(now);
if (nextExecution.isPresent()) {
long delayMillis = nextExecution.get().toMillis();
currentTask = scheduler.schedule(() -> {
takeScreenshot();
// Планируем следующее выполнение
scheduleCronTask(executionTime);
}, delayMillis, TimeUnit.MILLISECONDS);
}
}
/**
* Сделать скриншот
*/
private void takeScreenshot() {
String savePath = config.getSavePath();
String targetWindow = config.getTargetWindow();
screenshotService.captureAndSave(savePath, targetWindow);
}
/**
* Остановить планировщик
*/
public void stop() {
running = false;
if (currentTask != null) {
currentTask.cancel(false);
}
System.out.println("Планировщик остановлен");
}
/**
* Перезапустить с новыми настройками
*/
public void restart() {
stop();
screenshotService.resetImageComparison();
start();
}
/**
* Завершить работу
*/
public void shutdown() {
stop();
scheduler.shutdown();
try {
if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) {
scheduler.shutdownNow();
}
} catch (InterruptedException e) {
scheduler.shutdownNow();
Thread.currentThread().interrupt();
}
}
public boolean isRunning() {
return running;
}
}