package Visual_DVM_2021.Passes.All;
import Common.Current;
import Common.UI.UI;
import GlobalData.Compiler.CompilerType;
import GlobalData.Machine.MachineType;
import GlobalData.User.UserState;
import Repository.Server.ServerCode;
import Repository.Server.ServerExchangeUnit_2021;
import TestingSystem.Configuration.ConfigurationInterface;
import TestingSystem.Group.Group;
import TestingSystem.Group.GroupInterface;
import TestingSystem.Tasks.TestCompilationTask;
import TestingSystem.Tasks.TestRunTask;
import TestingSystem.TasksPackage.TasksPackage;
import TestingSystem.Test.Test;
import TestingSystem.TestingServer;
import Visual_DVM_2021.Passes.PassCode_2021;
import Visual_DVM_2021.Passes.TestingSystemPass;

import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Vector;
public class StartTests extends TestingSystemPass<TasksPackage> {
    @Override
    protected int getTimeout() {
        return 0;
    }
    @Override
    public String getIconPath() {
        return "/icons/Start.png";
    }
    @Override
    public String getButtonText() {
        return "";
    }
    @Override
    protected boolean canStart(Object... args) throws Exception {
        if (!Current.getAccount().CheckRegistered(Log)) {
            return false;
        }
        if (Current.Check(Log, Current.Machine, Current.User, Current.Compiler)) {
            if (!Current.getMachine().type.equals(MachineType.Server)) {
                Log.Writeln_("Тестирование поддерживается только на одиночном удалённом сервере.");
                return false;
            }
            if (!Current.getUser().state.equals(UserState.ready_to_work)) {
                Log.Writeln_("Пользователь не готов к работе. Выполните инициализацию пользователя!");
                return false;
            }
            if (!Current.getCompiler().type.equals(CompilerType.dvm)) {
                Log.Writeln_("Тестирование поддерживается только для DVM компиляторов.");
                return false;
            }
            if (!Current.getCompiler().versionLoaded)
                passes.get(PassCode_2021.ShowCompilerVersion).Do(Current.getCompiler(), false);
            if (!CreateTasks()) {
                Log.Writeln_("Не удалось создать задачи.\n" +
                        "Для создания задач отметьте требуемые конфигурации,\n" +
                        "Отметьте группы, или отдельные тесты в отмеченной текущей группе");
                return false;
            }
            //-
            if (target.runTasksCount == 0) {
                Log.Writeln_("Не будет создано ни одной задачи на запуск.");
                return false;
            }
            //todo сюда же флаг нужно ли почтовое отправление.
            if (UI.Question("Будет запущено:\n"
                    + target.compilationTasksCount + " задач на компиляцию\n" +
                    +target.runTasksCount + " задач на запуск.\n" +
                    "Продолжить")) {
                return true;
            }
        }
        return false;
    }
    public static Vector<TestCompilationTask> createTasksCGT(
            TestingSystem.Configuration.Configuration configuration,
            Group group,
            Test test
    ) {
        Vector<TestCompilationTask> compilationTasks = new Vector<>();
        for (String flags : ConfigurationInterface.getFlags(configuration)) {
            TestCompilationTask testCompilationTask = new TestCompilationTask(
                    configuration,
                    group,
                    test,
                    flags
            );
            testCompilationTask.runTasks = new Vector<>();
            Vector<String> matrixes = ConfigurationInterface.getMatrixes(configuration, test.dim);
            Vector<String> environments = ConfigurationInterface.getEnvironments(configuration);
            for (String environmentSet : environments) {
                if (flags.trim().equalsIgnoreCase("-s")) {
                    testCompilationTask.runTasks.add(new TestRunTask(
                            configuration,
                            group,
                            test,
                            "",
                            flags,
                            environmentSet,
                            ConfigurationInterface.getParamsText(configuration)
                    ));
                } else
                    for (String matrix : matrixes) {
                        testCompilationTask.runTasks.add(new TestRunTask(
                                configuration,
                                group,
                                test,
                                matrix,
                                flags,
                                environmentSet,
                                ConfigurationInterface.getParamsText(configuration)));
                    }
            }
            compilationTasks.add(testCompilationTask);
        }
        return compilationTasks;
    }
    protected boolean CreateTasks() {
        //---------
        Vector<String> configurations_lines = new Vector<>();
        Vector<String> groups_lines = new Vector<>();
        //-----------
        target = new TasksPackage();
        target.StartDate = new Date().getTime();
        //-
        target.machine_name = Current.getMachine().name;
        target.machine_address = Current.getMachine().address;
        target.machine_port = Current.getMachine().port;
        target.machine_type = Current.getMachine().type;
        //-
        target.user_name = Current.getUser().login;
        target.user_password = Current.getUser().password;
        target.user_workspace = Current.getUser().workspace;
        target.dvm_drv = Current.getCompiler().call_command;
        target.dvm_version = Current.getCompiler().getVersionInfo();
        target.kernels = TestingServer.kernels;
        Vector<TestCompilationTask> tasks = new Vector<>();
        //1, Проверяем выбраны ли конфиги.
        if (server.db.configurations.getCheckedCount() == 0) {
            Log.Writeln_("Не отмечена ни одна конфигурация тестирования.");
            return false;
        }
        if (server.db.groups.getCheckedCount() > 0) {
            //2 Проверяем выбраны ли группы.
            configurations_lines.add("Конфигурации: ");
            for (TestingSystem.Configuration.Configuration configuration : server.db.configurations.getCheckedItems()) {
                configurations_lines.add(ConfigurationInterface.getSummary(configuration));
                groups_lines.add("Группы: ");
                for (Group group : server.db.groups.getCheckedItems()) {
                    groups_lines.add(GroupInterface.getSummary(group));
                    Vector<Test> groupTests = new Vector<>();
                    Vector<Test> checkedGroupTests = new Vector<>();
                    for (Test test : server.db.tests.Data.values()) {
                        if (test.group_id.equals(group.id)) {
                            groupTests.add(test);
                            if (test.isSelected())
                                checkedGroupTests.add(test);
                        }
                    }
                    if (!groupTests.isEmpty()) {
                        if (checkedGroupTests.isEmpty()) {
                            for (Test test : groupTests)
                                tasks.addAll(createTasksCGT(configuration, group, test));
                        } else {
                            //добавляем только отмеченные.
                            for (Test test : checkedGroupTests) {
                                tasks.addAll(createTasksCGT(configuration, group, test));
                            }
                        }
                    }
                }
            }
        }
        //рассортировать по группам и тестам задачи.
        for (TestCompilationTask task : tasks) {
            target.compilationTasksCount++;
            target.runTasksCount += task.runTasks.size();
            LinkedHashMap<String, Vector<TestCompilationTask>> group_tasks = null;
            if (target.sorted_tasks.containsKey(task.group_id))
                group_tasks = target.sorted_tasks.get(task.group_id);
            else {
                group_tasks = new LinkedHashMap<>();
                target.sorted_tasks.put(task.group_id, group_tasks);
            }
            Vector<TestCompilationTask> test_tasks = null;
            if (group_tasks.containsKey(task.test_id))
                test_tasks = group_tasks.get((task.test_id));
            else {
                test_tasks = new Vector<>();
                group_tasks.put(task.test_id, test_tasks);
            }
            test_tasks.add(task);
        }
        Vector<String> summary_lines = new Vector<>();
        summary_lines.addAll(configurations_lines);
        summary_lines.addAll(groups_lines);
        target.summary =
                "Задач на компиляцию: " + target.compilationTasksCount + "\n" +
                        "Задач на запуск: " + target.runTasksCount + "\n" +
                        String.join("\n", summary_lines);
        target.needsEmail = TestingServer.email ? 1 : 0;
        return !tasks.isEmpty();
    }
    @Override
    protected void performPreparation() throws Exception {
    }
    @Override
    protected void ServerAction() throws Exception {
        target.genName();
        Vector<TasksPackage> packages = new Vector<>();
        packages.add(target);
        Command(new ServerExchangeUnit_2021(ServerCode.PublishAccountObjects, Current.getAccount().email, packages));
    }
    @Override
    protected void performDone() throws Exception {
        passes.get(PassCode_2021.SynchronizeTestsTasks).Do();
        /*
        if (!TestingServer.checkTasks)
            TestingServer.TimerOn();
         */
    }
    @Override
    protected void showDone() throws Exception {
        server.account_db.packages.ui_.Select(target.id);
      //  UI.getMainWindow().getTestingWindow().ShowAutoActualizeTestsState();
    }
    @Override
    protected void FocusResult() {
        UI.getMainWindow().getTestingWindow().FocusTestingTasks();
    }
}
