import core.ApplicationConfiguration;
import repositories.SolutionsRepository;
import repositories.TasksRepository;
import repositories.TeamsRepository;
import api.ProxyResource;
import api.TasksResource;
import api.TeamsResource;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import core.FlagChecker;
import core.TaskType;
import database.MongoDBConnector;
import io.dropwizard.Application;
import io.dropwizard.setup.Environment;
import objects.Flag;
import objects.Task;
import objects.Team;
import objects.User;

import java.util.ArrayList;
import java.util.Random;
import java.util.UUID;

/**
 * Created by gpietrus on 16.02.16.
 */
public class CTFApplication extends Application<ApplicationConfiguration> {

    @Override
    public void run(ApplicationConfiguration applicationConfiguration, Environment environment) throws Exception {

        MongoDBConnector dbConnector = new MongoDBConnector(applicationConfiguration);
        dbConnector.connect();

        //GENERATE TEAMS

        TeamsRepository teamsRepository = new TeamsRepository(dbConnector);
        teamsRepository.clean();

        int numberOfNewTeams = new Random().nextInt(20);
        int numberOfTeamMembers = 3;

        for (int i = 0; i < numberOfNewTeams; i++) {

            ArrayList<User> members = new ArrayList<>();
            for (int j = 0; j < numberOfTeamMembers; j++) {
                members.add(new User(String.valueOf(UUID.randomUUID()), "passwd", "email"));
            }

            teamsRepository.add(new Team(String.valueOf(UUID.randomUUID()), "description", members));
        }

        //GENERATE TEAMS END

        //GENERATE TASKS

        TasksRepository tasksRepository = new TasksRepository(dbConnector);
        tasksRepository.clean();

        int numberOfNewTasks = 20;

        for (int i = 0; i < numberOfNewTasks; i++) {
            Task task = new Task(String.valueOf(UUID.randomUUID()), i,
                    i % 2 == 0 ? TaskType.CRYPTO : TaskType.WEB,
                    Flag.newRandomFlag()
            );
            tasksRepository.add(task);
        }

        //GENERATE TASKS END

        //REGISTER RESOURCES
        Injector injector = createInjector(applicationConfiguration, dbConnector);
        environment.jersey().register(injector.getInstance(TeamsResource.class));
        environment.jersey().register(injector.getInstance(TasksResource.class));
        environment.jersey().register(injector.getInstance(ProxyResource.class));
    }

    //todo: inject dbonnector
    private Injector createInjector(ApplicationConfiguration applicationConfiguration, MongoDBConnector dbConnector) {
        return Guice.createInjector(new AbstractModule() {
            @Override
            protected void configure() {
                bind(ApplicationConfiguration.class).toInstance(applicationConfiguration);
                bind(MongoDBConnector.class).toInstance(dbConnector);

                TeamsRepository teamsRepository = new TeamsRepository(dbConnector);
                TasksRepository tasksRepository = new TasksRepository(dbConnector);
                SolutionsRepository solutionsRepository = new SolutionsRepository(dbConnector);
                FlagChecker flagChecker = new FlagChecker(applicationConfiguration, tasksRepository, teamsRepository, solutionsRepository);

                bind(TeamsRepository.class).toInstance(teamsRepository);
                bind(TasksRepository.class).toInstance(tasksRepository);

                bind(TeamsResource.class).toInstance(new TeamsResource(teamsRepository));
                bind(TasksResource.class).toInstance(new TasksResource(tasksRepository, teamsRepository,
                        solutionsRepository, flagChecker));
                bind(ProxyResource.class).toInstance(new ProxyResource());
                bind(FlagChecker.class).toInstance(flagChecker);
            }
        });
    }

    public static void main(String[] args) throws Exception {
        //todo: add mongo-java-driver as maven dep
        new CTFApplication().run(args);
    }
}
