package com.vshaldin.application;

import com.vshaldin.core.blocker.Blocker;
import com.vshaldin.core.domain.entity.BlockedEntity;
import com.vshaldin.core.loader.DBLoader;
import com.vshaldin.core.parser.FileParser;
import com.vshaldin.util.ArgumentsUtil;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * Parser application
 */

public class Application {

    private static final int POOL_SIZE = 5;

    private static final ExecutorService executor = Executors.newFixedThreadPool(POOL_SIZE);

    public static void main(String[] args) {

        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-context.xml");

        Arguments arguments = applicationContext.getBean(Arguments.class);
        FileParser fileParser = applicationContext.getBean(FileParser.class);
        Blocker blocker = applicationContext.getBean(Blocker.class);

        String argumentResult;

        if (args != null && args.length >= 3) {
            argumentResult = ArgumentsUtil.parseArguments(arguments, args);
            if (argumentResult != null) {
                System.out.println(argumentResult);
                ArgumentsUtil.printLegendAndExit();
            }
        } else {
            ArgumentsUtil.printLegendAndExit();
        }

        try {

            System.out.println("Initialization started");

            for (int i = 0; i < POOL_SIZE; i++) {
                executor.submit(applicationContext.getBean(DBLoader.class));
            }

            System.out.println("Initialization completed");
            System.out.println("Parsing started");

            long start = System.nanoTime();
            fileParser.parse();
            System.out.println("Parsing completed. Elapsed time: " + (System.nanoTime() - start) / 1_000_000 + " ms.");
            executor.shutdown();
            executor.awaitTermination(300, TimeUnit.SECONDS);

            System.out.println("Loading completed. Elapsed time: " + (System.nanoTime() - start) / 1_000_000 + " ms.");

            System.out.println("Searching started");

            start = System.nanoTime();

            List<BlockedEntity> blockedEntities = blocker.checkAndBlock();

            long end = System.nanoTime();

            if (blockedEntities != null) {
                StringBuilder stringBuilder = new StringBuilder();
                for (int i = 0; i < blockedEntities.size(); i++) {
                    BlockedEntity entity = blockedEntities.get(i);
                    stringBuilder.append(i).append(". Blocked: ").append(entity.getIpAddress()).append(". Reason: ")
                            .append(entity.getBlockingReason());
                    System.out.println(stringBuilder.toString());
                    stringBuilder.setLength(0);
                }
            }
            System.out.println("Searching completed. Elapsed time: " + (end - start) / 1_000_000 + " ms.");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}