package services;

import akka.actor.ActorSystem;
import managers.MediaManager;
import models.services.EmailService;
import org.joda.time.DateTime;
import org.joda.time.Seconds;
import scala.concurrent.duration.Duration;

import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.concurrent.TimeUnit;

/**
 * Created by Iven on 08.12.2015.
 */
@Singleton
public class ScheduleService {

    private EmailService emailService;
    private MediaManager mediaManager;
    private ActorSystem system;

    @Inject
    public ScheduleService(EmailService emailService, MediaManager mediaManager) {
        system = ActorSystem.create();
        this.emailService = emailService;
        this.mediaManager = mediaManager;
        schedule();
    }

    private void schedule() {

        // set the email schedule to next full hour clock for sending daily and hourly emails
        system.scheduler().schedule(
                Duration.create(nextExecutionInSeconds(getNextHour(), 0), TimeUnit.SECONDS),
                Duration.create(10, TimeUnit.MINUTES),
                () -> {
                    emailService.sendDailyHourlyNotificationsEmails();
                },
                system.dispatcher()
        );

        // Sets the schedule for cleaning the media temp directory
        system.scheduler().schedule(
                Duration.create(0, TimeUnit.MILLISECONDS),
                Duration.create(2, TimeUnit.HOURS),
                () -> {
                    mediaManager.cleanUpTemp();
                },
                system.dispatcher()
        );
    }

    /**
     * Returns the next full hour of the current time
     *
     * @return Next hour of current time
     */
    private int getNextHour() {
        return (new DateTime()).plusHours(1).getHourOfDay();
    }

    /**
     * Calculates seconds between now and a time for hour and minute.
     *
     * @param hour Hour
     * @param minute Minute
     * @return Seconds
     */
    private int nextExecutionInSeconds(int hour, int minute) {
        return Seconds.secondsBetween(
                new DateTime(),
                nextExecution(hour, minute)
        ).getSeconds();
    }

    /**
     * Returns a DateTime for hour and minute.
     *
     * @param hour Hour
     * @param minute Minute
     * @return DateTime
     */
    private DateTime nextExecution(int hour, int minute) {
        DateTime next = new DateTime()
                .withHourOfDay(hour)
                .withMinuteOfHour(minute)
                .withSecondOfMinute(0)
                .withMillisOfSecond(0);

        return (next.isBeforeNow())
                ? next.plusHours(24)
                : next;
    }
}

@@ -43,16 +43,47 @@
 System;%0A
+import akka.actor.Cancellable;%0A
 import m
@@ -202,16 +202,81 @@
 econds;%0A
+import play.api.inject.ApplicationLifecycle;%0Aimport play.libs.F;%0A
 import s
@@ -370,16 +370,63 @@
 gleton;%0A
+import java.util.concurrent.CompletableFuture;%0A
 import j
@@ -650,16 +650,60 @@
  system;
+%0A    private ApplicationLifecycle lifecycle;
 %0A%0A    @I
@@ -787,16 +787,48 @@
 aManager
+, ApplicationLifecycle lifecycle
 ) %7B%0A    
@@ -942,24 +942,60 @@
 diaManager;%0A
+        this.lifecycle = lifecycle;%0A
         sche
@@ -1133,32 +1133,61 @@
 y emails%0A       
+ Cancellable emailScheudler =
  system.schedule
@@ -1236,48 +1236,9 @@
 ate(
-nextExecutionInSeconds(getNextHour(), 0)
+0
 , Ti
@@ -1287,17 +1287,16 @@
 create(1
-0
 , TimeUn
@@ -1466,24 +1466,213 @@
         );%0A%0A
+        // cancel it on application stop%0A        lifecycle.addStopHook(() -%3E %7B%0A            emailScheudler.cancel();%0A            return CompletableFuture.completedFuture(null);%0A        %7D);%0A%0A
         // S
@@ -1729,24 +1729,55 @@
 tory%0A       
+ Cancellable cleanUpScheudler =
  system.sche
@@ -2042,16 +2042,207 @@
       );
+%0A%0A        // cancel it on application stop%0A        lifecycle.addStopHook(() -%3E %7B%0A            cleanUpScheudler.cancel();%0A            return CompletableFuture.completedFuture(null);%0A        %7D);
 %0A    %7D%0A%0A

stop scheudled tasks