package _VisualDVM.TestingSystem.Common;
import Common.CommonConstants;
import Common.Database.Objects.DBObject;
import Common.Database.Objects.riDBObject;
import Common.Database.RepositoryRefuseException;
import Common.Utils.Pair;
import Common.Utils.TextLog;
import Common.Utils.Utils_;
import Common.Utils.Vector_;
import _VisualDVM.ComponentsServer.Component.Sapfor.Sapfor;
import _VisualDVM.ComponentsServer.UserAccount.AccountRole;
import _VisualDVM.ComponentsServer.UserAccount.UserAccount;
import _VisualDVM.Constants;
import _VisualDVM.Global;
import _VisualDVM.GlobalData.Tasks.TaskState;
import _VisualDVM.Passes.All.DownloadDvmTestsRepository;
import _VisualDVM.Passes.All.ZipFolderPass;
import _VisualDVM.Passes.PassCode;
import _VisualDVM.ProjectData.LanguageName;
import _VisualDVM.Repository.EmailMessage;
import _VisualDVM.Repository.Server.RepositoryServer;
import _VisualDVM.Repository.Server.ServerCode;
import _VisualDVM.Repository.Server.ServerExchangeUnit_2021;
import _VisualDVM.TestingSystem.Common.Group.Group;
import _VisualDVM.TestingSystem.Common.MachineProcess.MachineProcess;
import _VisualDVM.TestingSystem.Common.MachineProcess.MachineProcessSet;
import _VisualDVM.TestingSystem.Common.Test.Test;
import _VisualDVM.TestingSystem.Common.Test.TestType;
import _VisualDVM.TestingSystem.Common.TestFile.TestFile;
import _VisualDVM.TestingSystem.Common.TestingPackageToKill.TestingPackageToKill;
import _VisualDVM.TestingSystem.DVM.DVMConfiguration.DVMConfiguration;
import _VisualDVM.TestingSystem.DVM.DVMConfigurationGroup.DVMConfigurationGroup;
import _VisualDVM.TestingSystem.DVM.DVMConfigurationSettings.DVMConfigurationSettings;
import _VisualDVM.TestingSystem.DVM.DVMConfigurationTest.DVMConfigurationTest;
import _VisualDVM.TestingSystem.DVM.DVMPackage.DVMPackage;
import _VisualDVM.TestingSystem.DVM.DVMSettings.DVMSettings;
import _VisualDVM.TestingSystem.DVM.DVMTestingChecker;
import _VisualDVM.TestingSystem.DVM.PackageCredentials.DVMPackageCredentials;
import _VisualDVM.TestingSystem.SAPFOR.Json.SapforPackage_json;
import _VisualDVM.TestingSystem.SAPFOR.Json.SapforVersion_json;
import _VisualDVM.TestingSystem.SAPFOR.SapforConfiguration.SapforConfiguration;
import _VisualDVM.TestingSystem.SAPFOR.SapforConfigurationGroup.SapforConfigurationGroup;
import _VisualDVM.TestingSystem.SAPFOR.SapforConfigurationSettings.SapforConfigurationSettings;
import _VisualDVM.TestingSystem.SAPFOR.SapforConfigurationTest.SapforConfigurationTest;
import _VisualDVM.TestingSystem.SAPFOR.SapforPackage.SapforPackage;
import _VisualDVM.TestingSystem.SAPFOR.SapforSettings.SapforSettings;
import _VisualDVM.TestingSystem.SAPFOR.SapforTask.SapforTask;
import _VisualDVM.TestingSystem.SAPFOR.SapforTestingPlanner;
import _VisualDVM.TestingSystem.SAPFOR.ServerSapfor.ServerSapfor;
import _VisualDVM.TestingSystem.SAPFOR.ServerSapfor.ServerSapforState;
import _VisualDVM.Utils;
import org.apache.commons.io.FileUtils;

import javax.swing.*;
import java.io.File;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.Vector;
public class TestingServer extends RepositoryServer<TestsDatabase> {
    public static MachineProcessSet machinesProcesses = new MachineProcessSet();
    //------>>>
    public static Timer checkTimer = null;
    public String name = "?";
    DVMTestingChecker dvmTestingChecker = null;
    SapforTestingPlanner sapforTestingPlanner = null;
    //-->
    MachinesDatabase machines_db;
    //-->
    public TestingServer() {
        super(TestsDatabase.class);
        name = Utils_.getDateName("testingServer");
    }
    public static void TimerOn() {
        checkTimer = new Timer(Global.normalProperties.CheckTestingIntervalSeconds * 1000, e -> {
            Global.mainModule.getPass(PassCode.ActualizePackages).Do();
        });
        checkTimer.start();
    }
    public static void TimerOff() {
        if (checkTimer != null)
            checkTimer.stop();
    }
    public static void ResetTimer() {
        TimerOff();
        TimerOn();
    }
    @Override
    public void StartAction() throws Exception {
        try {
            //--
            db.Patch();
            //--
            machines_db = new MachinesDatabase();
            machines_db.Activate();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
    @Override
    protected void extraBackup(File todayBackUp) {
        zip.Do("Tests", new File(todayBackUp, "Tests.zip").getAbsolutePath());
    }
    @Override
    protected void beforePublishAction(DBObject object) throws Exception {
        if (object instanceof ServerSapfor) {
            int current_version = getSapforActualVersion();
            int max_installed_version = db.getInstalledSapforMaxVersion();
            if (max_installed_version == current_version)
                throw new RepositoryRefuseException("Актуальная версия SAPFOR " + max_installed_version + " уже установлена");
            ServerSapfor serverSapfor = (ServerSapfor) object;
            serverSapfor.version = String.valueOf(current_version);
        }
    }
    @Override
    public void afterPublishAction(DBObject object) throws Exception {
        if (object instanceof Test) {
            Test test = (Test) object;
            if (!test.unpackProjectOnServer()) {
                db.Delete(test);
                throw new RepositoryRefuseException(
                        "Не удалось прикрепить проект к тесту с id " + test.id
                                + "\nТест будет удален"
                );
            }
            db.saveTestFiles(test);
            db.DetectTestMinMaxDim(db.serverSapfors.getLastDoneVersion(), db.groups.get(test.group_id), test);
        } else if (object instanceof DVMPackage) {
            DVMPackage dvmPackage = (DVMPackage) object;
            //--
            Utils_.CheckAndCleanDirectory(dvmPackage.getLocalWorkspace());
            //--
            dvmPackage.saveJson();
            dvmPackage.package_json = null; // объект больше не нужен.
            //--
            //Занести учетные данные пакета в базу о машинах. это основной поток, нить не нужна. арг это пароль
            DVMPackageCredentials credentials = new DVMPackageCredentials(dvmPackage, request.arg);
            machines_db.Insert(credentials);
            db.saveDVMPackageConfigurations(dvmPackage);
            //--
        } else if (object instanceof SapforPackage) {
            SapforPackage sapforPackage = (SapforPackage) object;
            sapforPackage.init();
            db.saveSapforPackageConfigurations(sapforPackage);
        } else if (object instanceof DVMSettings) {
            DVMSettings dvmSettings = (DVMSettings) object;
            db.InsertDVMSettingsOptions(dvmSettings);
            db.InsertDVMSettingsEnvironments(dvmSettings);
            dvmSettings.packedCompilationOptionsJson = null;
            dvmSettings.packedRunEnvironmentValuesJson = null;
        }
    }
    @Override
    protected void afterCloneAction(riDBObject src, riDBObject dst) throws Exception {
        if (src instanceof SapforSettings) {
            db.CloneSapforSettings((SapforSettings) src, (SapforSettings) dst);
        } else if (src instanceof DVMSettings) {
            db.CloneDVMSettings((DVMSettings) src, (DVMSettings) dst);
        }
    }
    @Override
    protected void afterEditAction(DBObject object) throws Exception {
        if (object instanceof DVMConfiguration) {
            DVMConfiguration dvmConfiguration = (DVMConfiguration) object;
            //--
            if (dvmConfiguration.groups != null)
                db.dvmConfigurationGroups.ActualizeData(
                        db.getVectorByFK(dvmConfiguration, DVMConfigurationGroup.class),
                        dvmConfiguration.groups);
            if (dvmConfiguration.tests != null)
                db.dvmConfigurationTests.ActualizeData(
                        db.getVectorByFK(dvmConfiguration, DVMConfigurationTest.class),
                        dvmConfiguration.tests);
            if (dvmConfiguration.settings != null)
                db.dvmConfigurationSettings.ActualizeData(
                        db.getVectorByFK(dvmConfiguration, DVMConfigurationSettings.class),
                        dvmConfiguration.settings);
            //--
        } else if (object instanceof SapforConfiguration) {
            SapforConfiguration sapforConfiguration = (SapforConfiguration) object;
            if (sapforConfiguration.groups != null)
                db.sapforConfigurationGroups.ActualizeData(
                        db.getVectorByFK(sapforConfiguration, SapforConfigurationGroup.class),
                        sapforConfiguration.groups
                );
            if (sapforConfiguration.tests != null)
                db.sapforConfigurationTests.ActualizeData(
                        db.getVectorByFK(sapforConfiguration, SapforConfigurationTest.class),
                        sapforConfiguration.tests
                );
            if (sapforConfiguration.settings != null)
                db.sapforConfigurationSettings.ActualizeData(
                        db.getVectorByFK(sapforConfiguration, SapforConfigurationSettings.class),
                        sapforConfiguration.settings
                );
        } else if (object instanceof DVMSettings) {
            DVMSettings dvmSettings = (DVMSettings) object;
            db.DeleteDVMSettingsOptions(dvmSettings);
            db.DeleteDVMSettingsEnvironments(dvmSettings);
            //--
            db.InsertDVMSettingsOptions(dvmSettings);
            db.InsertDVMSettingsEnvironments(dvmSettings);
            //--
            dvmSettings.packedCompilationOptionsJson = null;
            dvmSettings.packedRunEnvironmentValuesJson = null;
        }
    }
    @Override
    protected void afterDeleteAction(DBObject object) throws Exception {
        if (object instanceof Test) {
            Test test = (Test) object;
            Utils_.forceDeleteWithCheck(test.getServerPath());
            //--
        } else if (object instanceof Group) {
            Group group = (Group) object;
            LinkedHashMap<Integer, Test> groupTests = db.getMapByFKi(group, Test.class);
            //--
            for (Test group_test : groupTests.values()) {
                Utils_.forceDeleteWithCheck(group_test.getServerPath());
                db.DeleteDependencies(group_test);
            }
            //--
        } else if (object instanceof ServerSapfor) {
            Utils_.forceDeleteWithCheck(new File(((ServerSapfor) object).home_path));
        } else if (object instanceof DVMPackage) {
            DVMPackage dvmPackage = (DVMPackage) object;
            File workspace = dvmPackage.getLocalWorkspace();
            Utils_.forceDeleteWithCheck(workspace);
            //--
            DVMPackageCredentials credentials = machines_db.dvmPackagesCredentials.getForPackageId(dvmPackage.id);
            if (credentials != null)
                machines_db.Delete(credentials);
            //--
        } else if (object instanceof SapforPackage) {
            SapforPackage sapforPackage = (SapforPackage) object;
            //--
            for (SapforConfiguration sapforConfiguration : db.sapforConfigurations.Data.values()) {
                if (sapforConfiguration.ethalon_id == sapforPackage.id) {
                    sapforConfiguration.ethalon_id = CommonConstants.Nan;
                    db.Update(sapforConfiguration);
                }
            }
            //--
            File workspace = sapforPackage.getLocalWorkspace();
            Utils_.forceDeleteWithCheck(workspace);
        } else if (object instanceof DVMSettings) {
            DVMSettings dvmSettings = (DVMSettings) object;
            db.DeleteDVMSettingsOptions(dvmSettings);
        }
        //-
    }
    @Override
    public String getServerHomeName() {
        return "_testing_system";
    }
    //-->>>
    @Override
    public int getPort() {
        return Constants.TestingServerPort;
    }
    @Override
    protected void startAdditionalThreads() {
        dvmTestingChecker = new DVMTestingChecker();
        sapforTestingPlanner = new SapforTestingPlanner();
        new Thread(() -> {
            while (true) {
                dvmTestingChecker.Perform();
                sapforTestingPlanner.Perform();
                Utils_.sleep(5000);
            }
        }).start();
    }
    void PerformAutoSapforTesting() throws Exception {
        int sapforId = Integer.parseInt(request.arg);
        checkExistense(sapforId, ServerSapfor.class);
        ServerSapfor sapfor = db.serverSapfors.get(sapforId);
        TextLog Log = new TextLog();
        tryAutoSapforTesting(sapfor, Log);
        EmailMessage message = Log.isEmpty() ?
                new EmailMessage(
                        ("Запущено автоматическое тестирование версии " + sapfor.version + " системы SAPFOR"),
                        Log.toString()) :
                new EmailMessage(
                        "Не удалось запустить автоматическое тестирование версии " + sapfor.version + " системы SAPFOR",
                        Log.toString()
                );
        for (String address : Constants.admins_mails)
            EmailMessagesQueue.add(new Pair<>(address, message));
    }
    void DownloadTest() throws Exception {
        int test_id = Integer.parseInt(request.arg);
        checkExistense(test_id, Test.class);
        Test test = db.tests.get(test_id);
        File archive = new File(Global.TempDirectory, Utils_.getDateName(String.valueOf(test.id)));
        ZipFolderPass zipFolderPass = new ZipFolderPass();
        if (!zipFolderPass.Do(test.getServerPath().getAbsolutePath(), archive.getAbsolutePath()))
            throw new RepositoryRefuseException("Не удалось заархивировать тест");
        response = new ServerExchangeUnit_2021(ServerCode.OK, "", Utils_.fileToBytes(archive));
        FileUtils.forceDelete(archive);
    }
    void ReceiveTestsDatabase() throws Exception {
        response.object = Utils_.fileToBytes(db.getFile());
    }
    Pair<Group, Vector<File>> ConvertDirectoryToGroup(File src, LanguageName languageName, TestType
            testType, UserAccount account) throws Exception {
        Group object = new Group();
        Vector<File> groupFiles = null; //транспорт.
        //->>
        object.description = src.getName();
        object.language = languageName;
        object.type = testType;
        object.sender_name = account.name;
        object.sender_address = account.email;
        //-->>
        File[] files = src.listFiles(pathname ->
                pathname.isFile()
                        && !pathname.getName().equals("settings")
                        && !pathname.getName().equals("test-analyzer.sh")
                        && Utils_.getExtension(pathname).startsWith(languageName.getDVMCompile()));
        if (files != null) {
            groupFiles = new Vector<>(Arrays.asList(files));
            groupFiles.sort(Comparator.comparing(File::getName));
        }
        //->>
        return new Pair<>(object, groupFiles);
    }
    void RefreshDVMTests() throws Exception {
        UserAccount account = new UserAccount("server", Constants.MailAddress);
        ServerSapfor serverSapfor = db.serverSapfors.getLastDoneVersion();
        DownloadDvmTestsRepository downloadRepository = new DownloadDvmTestsRepository();
        if (!downloadRepository.Do())
            throw new RepositoryRefuseException("Не удалось обновить репозиторий");
        //-->>
        Vector<Pair<Group, Vector<File>>> groups = new Vector<>();
        File testsSrc = Paths.get(
                Global.RepoDirectory.getAbsolutePath(),
                "dvm-auto-test", "test-suite").toFile();
        LanguageName[] supportedLanguages = new LanguageName[]{LanguageName.fortran, LanguageName.c};
        for (LanguageName languageName : supportedLanguages) {
            for (TestType testType : TestType.values()) {
                File groupsSrc = null;
                switch (testType) {
                    case Correctness:
                        String languageSrcName = null;
                        switch (languageName) {
                            case fortran:
                                languageSrcName = "Fortran";
                                break;
                            case c:
                                languageSrcName = "C";
                                break;
                        }
                        if (languageSrcName != null) {
                            groupsSrc = Paths.get(testsSrc.getAbsolutePath(), "Correctness", languageSrcName).toFile();
                            File[] groupsDirs = groupsSrc.listFiles(File::isDirectory);
                            if (groupsDirs != null) {
                                for (File groupDir : groupsDirs)
                                    groups.add(ConvertDirectoryToGroup(groupDir, languageName, testType, account));
                            }
                        }
                        break;
                    case Performance:
                        File groupDir = Paths.get(testsSrc.getAbsolutePath(), "Performance").toFile();
                        groups.add(ConvertDirectoryToGroup(groupDir, languageName, testType, account));
                        break;
                }
            }
        }
        groups.sort(Comparator.comparing(o -> o.getKey().description));
        for (Pair<Group, Vector<File>> p : groups)
            db.RefreshGroup(account, serverSapfor, p);
    }
    void GetFirstActiveSapforPackages() throws Exception {
        response.object = db.getFirstActiveSapforPackagesCopies();
    }
    void GetSapforMaxVersion() throws Exception {
        response.object = db.getInstalledSapforMaxVersion();
    }
    void UpdateActiveDVMPackages() throws Exception {
        Vector<Pair<Integer, Long>> keys_pairs = (Vector<Pair<Integer, Long>>) request.object;
        Vector<DVMPackage> res = new Vector<>();
        //--
        for (Pair<Integer, Long> p : keys_pairs) {
            if (db.dvmPackages.containsKey(p.getKey())) {
                DVMPackage actual = db.dvmPackages.get(p.getKey());
                if (actual.ChangeDate != p.getValue())
                    res.add(new DVMPackage(actual));
            }
        }
        response.object = res;
    }
    void UpdateActiveSapforPackages() {
        Vector<Pair<Integer, Long>> keys_pairs = (Vector<Pair<Integer, Long>>) request.object;
        Vector<SapforPackage> res = new Vector<>();
        //--
        for (Pair<Integer, Long> p : keys_pairs) {
            if (db.sapforPackages.containsKey(p.getKey())) {
                SapforPackage actual = db.sapforPackages.get(p.getKey());
                if (actual.ChangeDate != p.getValue())
                    res.add(new SapforPackage(actual));
            }
        }
        response.object = res;
    }
    void DVMPackageNeedsKill() {
        response.object = CommonConstants.Nan;
        int packageId = (int) request.object;
        for (TestingPackageToKill packageToKill : db.testingPackagesToKill.Data.values()) {
            if ((packageToKill.packageId == packageId) && (packageToKill.type == 0)) {
                response.object = packageToKill.id;
                break;
            }
        }
    }
    void SapforPackageNeedsKill() throws Exception {
        response.object = CommonConstants.Nan;
        int packageId = (int) request.object;
        for (TestingPackageToKill packageToKill : db.testingPackagesToKill.Data.values()) {
            if ((packageToKill.packageId == packageId) && (packageToKill.type == 1)) {
                response.object = packageToKill.id;
                break;
            }
        }
    }
    void DownloadDVMPackages() throws Exception {
        Vector<Integer> ids = (Vector<Integer>) request.object;
        Vector<Pair<Integer, Pair<byte[], byte[]>>> res = new Vector<>();
        for (int dvmPackage_id : ids) {
            checkExistense(dvmPackage_id, DVMPackage.class);
            DVMPackage dvmPackage = db.dvmPackages.get(dvmPackage_id);
            File workspace = dvmPackage.getLocalWorkspace();
            File results_zip = new File(workspace, "results.zip");
            File package_json = dvmPackage.getJsonFile();
            res.add(new Pair<>(dvmPackage_id, new Pair(Utils_.fileToBytes(results_zip), Utils_.fileToBytes(package_json))));
        }
        response.object = res;
    }
    void DownloadSapforPackage() throws Exception {
        int sapforPackage_id = (int) request.object;
        checkExistense(sapforPackage_id, SapforPackage.class);
        SapforPackage sapforPackage = db.sapforPackages.get(sapforPackage_id);
        File workspace = sapforPackage.getLocalWorkspace();
        File results_zip = Utils.getTempFileName("results");
        ZipFolderPass zipFolderPass = new ZipFolderPass();
        zipFolderPass.Do(workspace.getAbsolutePath(), results_zip.getAbsolutePath());
        if (results_zip.exists())
            response.object = Utils_.fileToBytes(results_zip);
        else
            throw new RepositoryRefuseException("Не удалось заархивировать пакет тестирования SAPFOR с ключом " + sapforPackage_id);
    }
    void replaceTestCode(Test test, ServerSapfor serverSapfor) throws Exception {
        if (!test.unpackProjectOnServer()) {
            db.Delete(test);
            db.DeleteTestFiles(test);
            throw new RepositoryRefuseException(
                    "Не удалось прикрепить проект к тесту с id " + test.id
                            + "\nТест будет удален"
            );
        } else {
            db.Update(test);
            //--
            db.DeleteTestFiles(test);
            db.saveTestFiles(test);
            //--
            db.DetectTestMinMaxDim(serverSapfor, db.groups.get(test.group_id), test);
        }
    }
    void ReplaceTestCode() throws Exception {
        replaceTestCode((Test) request.object, db.serverSapfors.getLastDoneVersion());
    }
    void ReplaceTestsCodes() throws Exception {
        ServerSapfor serverSapfor = db.serverSapfors.getLastDoneVersion();
        for (Test test : (Vector<Test>) request.object)
            replaceTestCode(test, serverSapfor);
    }
    void GetServerName() throws Exception {
        response.object = name;
    }
    //--
    void GetFirstActiveDVMPackageForMachineURL() {
        response.object = db.getFirstActiveDVMPackageCopyForMachineURL(request.arg);
    }
    void StartNecessaryMachines() {
        try {
            Vector<String> aborted = new Vector<>();
            for (MachineProcess process : machinesProcesses.Data.values()) {
                if (process.isAborted()) {
                    aborted.add(process.id);
                }
            }
            //---
            for (String key : aborted) {
                machinesProcesses.Data.remove(key);
            }
            //---
            LinkedHashMap<String, MachineProcess> processes_to_start = new LinkedHashMap<>();
            //1. Получить список всех пакетов, которые активны, и взять из них машины.
            for (DVMPackage dvmPackage : db.dvmPackages.Data.values()) {
                if (dvmPackage.state.isActive()) {
                    //-
                    if (!machinesProcesses.hasProcessForPackage(dvmPackage)) {
                        DVMPackageCredentials credentials = machines_db.dvmPackagesCredentials.getForPackageId(dvmPackage.id);
                        if (credentials != null) {
                            MachineProcess new_process = new MachineProcess(dvmPackage, credentials);
                            //получить пароль.
                            processes_to_start.put(new_process.getUniqueKey(), new_process);
                        }
                    }
                }
            }
            //запуск.
            for (MachineProcess process : processes_to_start.values()) {
                process.Start();
                if (Utils.checkFileCreation(process.getStartedFile())) {
                    machinesProcesses.Data.put(process.id, process);
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
    //---
    int getSapforActualVersion() throws Exception {
        File versionFile = new File(Global.TempDirectory, "version.h");
        if (versionFile.exists())
            FileUtils.forceDelete(versionFile);
        //1. Получить версию из репозитория.
        Utils.startScript(Global.TempDirectory,
                Global.TempDirectory,
                "get_version",
                "wget -P " +
                        Utils_.DQuotes(Global.TempDirectory.getAbsolutePath()) +
                        "  " + Utils_.DQuotes(Constants.SAPFOR_VERSION_URL)
        ).waitFor();
        if (!versionFile.exists())
            throw new RepositoryRefuseException("Не удалось загрузить текущую версию SAPFOR из репозитория!");
        return Sapfor.readVersionFromCode(versionFile);
    }
    void GetSapforForCompilation() throws Exception {
        //1. Проверить наличие заказов от пользователя
        ServerSapfor serverSapfor = db.getSapforCopyForCompilation();
        if (serverSapfor == null) {
            //2 если нет. проверить есть ли свежие версии.
            int max_version = db.getInstalledSapforMaxVersion();
            int current_version = getSapforActualVersion();
            if (current_version > max_version) {
                ServerSapfor versionSapfor = db.getSapforForVersion(String.valueOf(current_version));
                if (versionSapfor == null || !versionSapfor.state.equals(ServerSapforState.DoneWithErrors)) {
                    serverSapfor = new ServerSapfor();
                    serverSapfor.sender_name = "server";
                    serverSapfor.sender_address = Constants.MailAddress;
                    serverSapfor.version = String.valueOf(current_version);
                    serverSapfor.state = ServerSapforState.Queued;
                    db.Insert(serverSapfor);
                }
            }
        }
        response.object = serverSapfor;
    }
    void tryAutoSapforTesting(ServerSapfor sapfor, TextLog Log) throws Exception {
        //--
        UserAccount account = new UserAccount();
        account.name = "server";
        account.email = Constants.MailAddress;
        account.role = AccountRole.Admin;
        //-
        if (!sapfor.state.equals(ServerSapforState.Done)) {
            Log.Writeln_("Выбранная версия SAPFOR " + sapfor.version + " не собрана!");
            return;
        }
        Vector<SapforConfiguration> configurations = db.sapforConfigurations.getAutoConfigurations();
        if (configurations.isEmpty()) {
            Log.Writeln_("Не найдено конфигураций для автоматического тестирования!");
            return;
        }
        Vector<SapforPackage> sapforPackages = new Vector<>();
        for (SapforConfiguration sapforConfiguration : configurations) {
            SapforPackage sapforPackage = new SapforPackage(account, sapfor, new Vector_<>(sapforConfiguration), 1, Log);
            if (sapforPackage.tasksCount > 0) {
                sapforPackages.add(sapforPackage);
            }
        }
        if (sapforPackages.isEmpty()) {
            Log.Writeln_("Не сформировано ни одного пакета");
            return;
        }
        for (SapforPackage sapforPackage : sapforPackages) {
            beforePublishAction(sapforPackage);
            db.InsertS(sapforPackage);
            afterPublishAction(sapforPackage);
        }
    }
    Vector<String> getSapforTaskResults(SapforTask task) throws Exception {
        Vector<String> res = new Vector<>();
        //--
        if (!task.variants.isEmpty()) {
            for (SapforVersion_json version_json : task.variants) {
                res.add(version_json.version);
            }
        } else {
            if (!task.versions.isEmpty()) {
                res.add(task.versions.lastElement().version);
            }
        }
        return res;
    }
    void JoinSapforPackageToGroup() throws Exception {
        String[] packed = request.arg.split("\n");
        int groupId = Integer.parseInt(packed[0]);
        int packageId = Integer.parseInt(packed[1]);
        checkExistense(packageId, SapforPackage.class);
        checkExistense(groupId, Group.class);
        //--
        SapforPackage sapforPackage = db.sapforPackages.get(packageId);
        Group group = db.groups.get(groupId);
        //--
        SapforPackage_json json = Utils_.jsonFromFile(sapforPackage.getJsonFile(), SapforPackage_json.class);
        LinkedHashMap<String, File> versions = new LinkedHashMap<>();
        LinkedHashMap<String, String> descriptions = new LinkedHashMap<>();
        for (SapforTask task : json.tasks) {
            if (task.state.equals(TaskState.Done)) {
                File task_root = Paths.get(
                        sapforPackage.getLocalWorkspace().getAbsolutePath(),
                        String.valueOf(task.set_id),
                        String.valueOf(task.sapfor_configuration_id)
                ).toFile();
                for (String path : getSapforTaskResults(task)) {
                    File versionProject = Paths.get(task_root.getAbsolutePath(), path).toFile();
                    Vector<String> name_parts = new Vector_<>(
                            String.valueOf(task.id),
                            task.test_description,
                            versionProject.getName()
                    );
                    String name = String.join("_", name_parts);
                    versions.put(name, versionProject);
                    //--
                    String[] data = task.codes.split(" ");
                    Vector<String> codes_ = new Vector<>();
                    for (String datum : data) {
                        PassCode code = PassCode.valueOf(datum);
                        codes_.add(code.getDescription());
                        //--
                        descriptions.put(name, String.join("\n", codes_));
                    }
                }
            }
        }
        //создание тестов.
        ServerSapfor serverSapfor = db.serverSapfors.getLastDoneVersion();
        for (String name : versions.keySet()) {
            File src = versions.get(name);
            File[] files = src.listFiles(pathname -> !pathname.isDirectory());
            if (files != null && files.length > 0) {
                //--
                Test test = new Test();
                test.group_id = group.id;
                test.description = name;
                test.sender_address = group.sender_address;
                test.sender_name = group.sender_name;
                test.extended_description = descriptions.get(name);
                db.Insert(test);
                //---
                Vector<TestFile> testFiles = new Vector<>();
                for (File file : files)
                    testFiles.add(new TestFile(test, file));
                db.BeginTransaction();
                for (TestFile testFile : testFiles)
                    db.Insert(testFile);
                db.Commit();
                //---
                File testProject = new File(Global.TestsDirectory, String.valueOf(test.id));
                //---
                if (testProject.exists())
                    FileUtils.forceDelete(testProject);
                FileUtils.copyDirectory(src, testProject);
                //---
                db.DetectTestMinMaxDim(serverSapfor, group, test);
            }
        }
    }
    void ReplaceDVMPackageJson() throws Exception {
        Pair<DVMPackage, byte[]> p = (Pair<DVMPackage, byte[]>) request.object;
        DVMPackage src = p.getKey();
        byte[] packed_file = p.getValue();
        checkExistense(src.id, DVMPackage.class);
        DVMPackage dst = db.dvmPackages.get(src.id);
        dst.SynchronizeFields(src);
        db.Update(dst);
        Utils_.bytesToFile(packed_file, dst.getJsonFile());
    }
    void ReplaceSapforPackageJson() throws Exception {
        Pair<SapforPackage, byte[]> p = (Pair<SapforPackage, byte[]>) request.object;
        SapforPackage src = p.getKey();
        byte[] packed_file = p.getValue();
        checkExistense(src.id, SapforPackage.class);
        SapforPackage dst = db.sapforPackages.get(src.id);
        dst.SynchronizeFields(src);
        db.Update(dst);
        Utils_.bytesToFile(packed_file, dst.getJsonFile());
    }
    void DetectTestsMinMaxDim() throws Exception {
        Vector<Object> keys = (Vector<Object>) request.object;
        for (Object key : keys) {
            checkExistense(key, Test.class);
        }
        ServerSapfor serverSapfor = db.serverSapfors.getLastDoneVersion();
        for (Object key : keys) {
            Test test = db.tests.get(key);
            Group group = db.groups.get(test.group_id);
            db.DetectTestMinMaxDim(serverSapfor, group, test);
        }
    }
    void GetDVMPackageCredentials() throws Exception {
        int package_id = (int) request.object;
        checkExistense(package_id, DVMPackage.class);
        DVMPackageCredentials res = machines_db.dvmPackagesCredentials.getForPackageId(package_id);
        if (res == null)
            throw new RepositoryRefuseException("Не найдено учетных данных для пакета " + Utils_.Brackets(package_id));
        response.object = res;
    }
    //--
    @Override
    protected void Session() throws Exception {
        switch (code) {
            case GetDVMPackageCredentials:
                GetDVMPackageCredentials();
                break;
            case PerformAutoSapforTesting:
                PerformAutoSapforTesting();
                break;
            case DownloadTest:
                DownloadTest();
                break;
            case ReceiveTestsDatabase:
                ReceiveTestsDatabase();
                break;
            case RefreshDVMTests:
                RefreshDVMTests();
                break;
            case DVMPackageNeedsKill:
                DVMPackageNeedsKill();
                break;
            case UpdateActiveDVMPackages:
                UpdateActiveDVMPackages();
                break;
            case GetFirstActiveSapforPackages:
                GetFirstActiveSapforPackages();
                break;
            case SapforPackageNeedsKill:
                SapforPackageNeedsKill();
                break;
            case UpdateActiveSapforPackages:
                UpdateActiveSapforPackages();
                break;
            case DownloadDVMPackages:
                DownloadDVMPackages();
                break;
            case DownloadSapforPackage:
                DownloadSapforPackage();
                break;
            case ReplaceTestCode:
                ReplaceTestCode();
                break;
            case ReplaceTestsCodes:
                ReplaceTestsCodes();
                break;
            case GetFirstActiveDVMPackageForMachineURL:
                GetFirstActiveDVMPackageForMachineURL();
                break;
            case GetServerName:
                GetServerName();
                break;
            case StartNecessaryMachines:
                StartNecessaryMachines();
                break;
            case GetSapforForCompilation:
                GetSapforForCompilation();
                break;
            case GetMaxSapforVersion:
                GetSapforMaxVersion();
                break;
            case JoinSapforVersionsToGroup:
                JoinSapforPackageToGroup();
                break;
            case ReplaceDVMPackageResults:
                ReplaceDVMPackageJson();
                break;
            case ReplaceSapforPackageResults:
                ReplaceSapforPackageJson();
                break;
            case DetectTestsMinMaxDim:
                DetectTestsMinMaxDim();
                break;
            default:
                throw new RepositoryRefuseException("Неподдерживаемый код: " + code);
        }
    }
}

