package edu.fiu;

import edu.fiu.controllers.ActivityController;
import edu.fiu.controllers.ActivityProgressController;
import edu.fiu.controllers.SessionController;
import edu.fiu.controllers.SubmitStoryController;
import edu.fiu.controllers.UserController;
import edu.fiu.repositories.ActivityRepository;
import edu.fiu.repositories.ActivityProgressRepository;
import edu.fiu.repositories.SessionRepository;
import edu.fiu.repositories.UserRepository;
import edu.fiu.repositories.UserStoryRepository;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.jdbi.v3.core.Jdbi;
import org.jdbi.v3.sqlobject.SqlObjectPlugin;
import org.jooby.*;
import org.jooby.jdbc.Jdbc;
import org.jooby.jdbi.Jdbi3;
import org.jooby.jdbi.TransactionalRequest;
import org.jooby.json.Jackson;

/**
 * Main entry point for MIMC backend application Lists routes available and sets
 * entry point for the various subsystems in the App
 *
 * @author Dan Herrera
 */
public class App extends Jooby {

  private final long cleanTimerMinutes = 1;

  // Inner Class
  Runnable runnableTask = () -> {
    Jdbi jdbi = require(Jdbi.class);
    jdbi.useHandle(h -> {
      CleanUp.cleanSessions(h);
      CleanUp.cleanLogIns(h);
    });
  };

  {
    // Dependencies
    use(new Jackson());
    use(new Jdbc());
    use(new Jdbi3()
        // plug plugin
        .doWith(jdbi -> {
          jdbi.installPlugin(new SqlObjectPlugin());
        })
        .transactionPerRequest(new TransactionalRequest().attach(UserRepository.class).attach(ActivityRepository.class)
            .attach(ActivityProgressRepository.class).attach(SessionRepository.class)
            .attach(UserStoryRepository.class)));

    onStart(() -> {
      Jdbi jdbi = require(Jdbi.class);
      jdbi.useHandle(h -> {
        //DbInitializer.Initialize(h);
        DbInitializer.Seed(h);
        ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
        executorService.scheduleAtFixedRate(runnableTask, 0, cleanTimerMinutes, TimeUnit.MINUTES);
      });
    });

    onStarted(() -> {
    });

    // Before each request
    before((req, rsp) -> {
      // Add cors header cause why not
      rsp.header("Access-Control-Allow-Origin", "*");

      // Check Authentication
      Authorize.checkSession(req, rsp, require(SessionRepository.class), require(UserRepository.class));
    });

    // Controllers
    use(ActivityController.class);
    use(ActivityProgressController.class);
    use(SessionController.class);
    use(UserController.class);
    use(SubmitStoryController.class);

    assets("**");
    assets("/", "index.html");

  }

  public static void main(final String[] args) {
    run(App::new, args);
  }

}