package TestingSystem;
import Common.Database.SQLITE.SQLiteDatabase;
import Common.Global;
import GlobalData.Settings.SettingName;
import SapforTestingSystem.SapforTask.SapforTasksDBTable;
import SapforTestingSystem.SapforTasksPackage.SapforTasksPackage;
import SapforTestingSystem.SapforTasksPackage.SapforTasksPackagesDBTable;
import TestingSystem.TSetting.TSetting;
import TestingSystem.TSetting.TSettingsDBTable;
import TestingSystem.Tasks.TestCompilationTask;
import TestingSystem.Tasks.TestCompilationTasksDBTable;
import TestingSystem.Tasks.TestRunTask;
import TestingSystem.Tasks.TestRunTasksDBTable;
import TestingSystem.TasksPackage.TasksPackage;
import TestingSystem.TasksPackage.TasksPackageDBTable;
import TestingSystem.TasksPackage.TasksPackageState;
import TestingSystem.TasksPackageToKill.TasksPackageToKillDBTable;
import javafx.util.Pair;

import java.io.File;
import java.nio.file.Paths;
import java.sql.PreparedStatement;
import java.util.LinkedHashMap;
import java.util.Vector;
public class TasksDatabase extends SQLiteDatabase {
    public static final String tests_db_name = "tests2023";
    public TSettingsDBTable settings;
    public TasksPackageDBTable packages;
    public TasksPackageToKillDBTable packagesToKill;
    public TestCompilationTasksDBTable testCompilationTasks;
    public TestRunTasksDBTable testRunTasks;
    PreparedStatement selectPackageRunTasks = null;
    //----------
    public SapforTasksPackagesDBTable sapforTasksPackages;
    public SapforTasksDBTable sapforTasks;
    //---------
    public TasksDatabase(String email) {
        super(Paths.get(Global.DataDirectory.getAbsolutePath(), email + "_" + tests_db_name + ".sqlite").toFile());
    }
    public TasksDatabase(File file_in) {
        super(file_in);
    }
    public void setFile(String email) {
        file = Paths.get(Global.DataDirectory.getAbsolutePath(), email + "_" + tests_db_name + ".sqlite").toFile();
    }
    @Override
    protected void initAllTables() throws Exception {
        addTable(settings = new TSettingsDBTable());
        addTable(packages = new TasksPackageDBTable());
        addTable(testCompilationTasks = new TestCompilationTasksDBTable());
        addTable(testRunTasks = new TestRunTasksDBTable());
        addTable(packagesToKill = new TasksPackageToKillDBTable());
        //-----------
        addTable(sapforTasksPackages = new SapforTasksPackagesDBTable());
        addTable(sapforTasks = new SapforTasksDBTable());
    }
    @Override
    public void Init() throws Exception {
        if (!settings.containsKey(SettingName.Email))
            Insert(new TSetting(SettingName.Email, 0));
        if (!settings.containsKey(SettingName.Pause))
            Insert(new TSetting(SettingName.Pause, 0));
        if (!settings.containsKey(SettingName.Queue))
            Insert(new TSetting(SettingName.Queue, 0));
    }
    @Override
    public void prepareTablesStatements() throws Exception {
        super.prepareTablesStatements();
        selectPackageRunTasks = conn.prepareStatement("SELECT * FROM TestRunTask WHERE taskspackage_id = ?");
    }
    @Override
    protected void disconnect() throws Exception {
        if (selectPackageRunTasks != null) {
            selectPackageRunTasks.close();
            selectPackageRunTasks = null;
        }
        super.disconnect();
    }
    public LinkedHashMap<Long, TestRunTask> getPackageRunTasks(String package_id) throws Exception {
        LinkedHashMap<Long, TestRunTask> res = new LinkedHashMap<>();
        selectPackageRunTasks.setString(1, package_id);
        resSet = selectPackageRunTasks.executeQuery();
        while (resSet.next()) {
            Pair<Long, TestRunTask> record = readRecord(testRunTasks);
            res.put(record.getKey(), record.getValue());
        }
        return res;
    }
    //------
    public TasksPackage getFirstActivePackage() {
        TasksPackage first_active = null;
        TasksPackage first_queued = null;
        if (!packages.Data.isEmpty()) {
            for (TasksPackage p : packages.Data.values()) {
                switch (p.state) {
                    case Done:
                    case Aborted:
                        break;
                    case Queued:
                        if (first_queued == null) first_queued = p;
                        break;
                    default:
                        if (first_active == null) first_active = p; //это и будет первый активный.
                        break;
                }
            }
            if (first_active != null) return first_active;
            if (first_queued != null) {
                first_queued.state = TasksPackageState.TestsSynchronize;
                try {
                    Update(first_queued);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            return first_queued;
        }
        return null;
    }
    public LinkedHashMap<Long, TestCompilationTask> getPackageCompilationTasks(TasksPackage tasksPackage) {
        if (tasksPackage == null) return null;
        LinkedHashMap<Long, TestCompilationTask> res = new LinkedHashMap<>();
        for (TestCompilationTask srcCompilationTask : testCompilationTasks.Data.values()) {
            if (srcCompilationTask.taskspackage_id.equals(tasksPackage.id)) {
                TestCompilationTask dstCompilationTask = new TestCompilationTask(srcCompilationTask);
                dstCompilationTask.runTasks = new Vector<>();
                for (TestRunTask testRunTask : testRunTasks.Data.values())
                    if (testRunTask.testcompilationtask_id == srcCompilationTask.id)
                        dstCompilationTask.runTasks.add(new TestRunTask(testRunTask));
                res.put(dstCompilationTask.id, dstCompilationTask);
            }
        }
        return res;
    }
    public long getQueueSize(long date) throws Exception {
        long sum = 0L;
        for (TasksPackage tasksPackage : packages.Data.values()) {
            if (tasksPackage.StartDate < date) {
                Vector<TestRunTask> tasks = new Vector<>(getPackageRunTasks(tasksPackage.id).values());
                for (TestRunTask testRunTask : tasks)
                    if (testRunTask.compilation_state.isActive() || testRunTask.state.isActive())
                        sum++;
            }
        }
        return sum;
    }
    //--
    public Vector<TasksPackage> getActivePackages() {
        Vector<TasksPackage> res = new Vector<>();
        for (TasksPackage p : packages.Data.values())
            if (!p.state.equals(TasksPackageState.Done))
                res.add(p);
        return res;
    }
    public Vector<SapforTasksPackage> getActiveSapforPackages() {
        Vector<SapforTasksPackage> res = new Vector<>();
        for (SapforTasksPackage p : sapforTasksPackages.Data.values())
            if (!p.state.equals(TasksPackageState.Done))
                res.add(p);
        return res;
    }
    public SapforTasksPackage getFirstActiveSapforPackage() {
        SapforTasksPackage first_active = null;
        SapforTasksPackage first_queued = null;
        if (!sapforTasksPackages.Data.isEmpty()) {
            for (SapforTasksPackage p : sapforTasksPackages.Data.values()) {
                switch (p.state) {
                    case Done:
                    case Aborted:
                        break;
                    case Queued:
                        if (first_queued == null) first_queued = p;
                        break;
                    default:
                        if (first_active == null) first_active = p; //это и будет первый активный.
                        break;
                }
            }
            if (first_active != null) return first_active;
            if (first_queued != null) {
                first_queued.state = TasksPackageState.TestsSynchronize;
                try {
                    Update(first_queued);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            return first_queued;
        }
        return null;
    }
}
