package _VisualDVM;
import Common.Utils.Loggable;
import Common.Utils.Utils_;
import Common.Visual.UI;
import _VisualDVM.ComponentsServer.Component.ComponentsSet;
import _VisualDVM.ComponentsServer.Component.PerformanceAnalyzer.PerformanceAnalyzer;
import _VisualDVM.ComponentsServer.Component.Sapfor.MessagesServer;
import _VisualDVM.ComponentsServer.Component.Visualiser;
import _VisualDVM.ComponentsServer.Component.Visualizer_2;
import _VisualDVM.ComponentsServer.ComponentsServer;
import _VisualDVM.Passes.PassCode;
import _VisualDVM.ProjectData.ProjectView;
import _VisualDVM.TestingSystem.Common.TestingServer;
import _VisualDVM.TestingSystem.DVM.RemoteDVMTestingPlanner;
import _VisualDVM.TestingSystem.SAPFOR.PackageModeSupervisor;
import org.fife.ui.rsyntaxtextarea.AbstractTokenMakerFactory;
import org.fife.ui.rsyntaxtextarea.TokenMakerFactory;

import java.io.File;
import java.nio.file.Paths;
public class Global {
    //todo свести большинство к содержимому mainModule
    public static MainModule mainModule = null;
    //Режим
    public static Mode mode = Mode.Undefined;
    //setAdminRights-------------
    public static VisualDVMProperties properties = null;
    public static NormalProperties normalProperties = null;
    public static ComponentsServerProperties componentsServerProperties = null;
    public static TestingServerProperties testingServerProperties = null;
    //---
    public static boolean files_multiselection = false;
    public static boolean versions_multiselection = false;
    //??
    public static ComponentsSet components = null;
    public static MessagesServer messagesServer = null;
    public static File ComponentsDirectory;
    public static File KeysDirectory;
    public static File DataDirectory;
    public static File BugReportsDirectory;
    public static File BackUpsDirectory; //бекапы компонентов на локальной машине.
    public static File TempDirectory;
    public static File ProjectsDirectory;
    public static File CompilationTasksDirectory;
    public static File RunTasksDirectory;
    public static File StsDirectory;
    public static File RepoDirectory;
    public static File TestsDirectory;
    public static File PerformanceAnalyzerDirectory;
    public static File DataBackUpsDirectory; //бекапы данных сервера.
    public static File DVMPackagesDirectory;
    public static File SapforsDirectory;
    public static File SapforPackagesDirectory;
    public static File MachinesDirectory;
    //------------------------------------------------------------------
    public static ComponentsServer componentsServer = new ComponentsServer();
    public static TestingServer testingServer = new TestingServer();
    public static PerformanceAnalyzer performanceAnalyzer = null;
    //------------------------------------------------------------------
    public static Visualiser visualiser = null;
    public static Visualizer_2 visualizer_2 = null;
    public static void CheckVisualiserDirectories() {
        Utils_.CheckAndCleanDirectory(TempDirectory = new File(Utils_.getHomeDirectory(), Constants.TempDirectoryName));
        Utils_.CheckDirectory(ComponentsDirectory = new File(Utils_.getHomeDirectory(), Constants.ComponentsDirectoryName));
        Utils_.CheckDirectory(DataDirectory = new File(Utils_.getHomeDirectory(), Constants.DataDirectoryName));
        //-
        Utils_.CheckDirectory(RepoDirectory = new File(Utils_.getHomeDirectory(), Constants.RepoDirectoryName));
        Utils_.CheckDirectory(BugReportsDirectory = new File(Utils_.getHomeDirectory(), "BugReports"));
        Utils_.CheckDirectory(BackUpsDirectory = new File(Utils_.getHomeDirectory(), Constants.BackUpsDirectoryName));
        Utils_.CheckDirectory(ProjectsDirectory = new File(Utils_.getHomeDirectory(), Constants.ProjectsDirectoryName));
        Utils_.CheckDirectory(CompilationTasksDirectory = new File(Utils_.getHomeDirectory(), Constants.CompilationTasksDirectoryName));
        Utils_.CheckDirectory(RunTasksDirectory = new File(Utils_.getHomeDirectory(), Constants.RunTasksDirectoryName));
        Utils_.CheckDirectory(StsDirectory = new File(Utils_.getHomeDirectory(), Constants.StsDirectoryName));
        Utils_.CheckDirectory(TestsDirectory = new File(Utils_.getHomeDirectory(), Constants.TestsDirectoryName));
        Utils_.CheckDirectory(PerformanceAnalyzerDirectory = new File(Utils_.getHomeDirectory(), Constants.PerformanceAnalyzerDirectoryName));
        Utils_.CheckDirectory(DVMPackagesDirectory = new File(Utils_.getHomeDirectory(), Constants.DVMPackagesDirectoryName));
        Utils_.CheckDirectory(SapforPackagesDirectory = new File(Utils_.getHomeDirectory(), "SapforPackages"));
        Utils_.CheckDirectory(KeysDirectory = new File(Utils_.getHomeDirectory(), Constants.KeyDirectoryName));
        try {
            Utils_.forceDeleteWithCheck(new File(DataDirectory, "credentials.sqlite"));
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
    public static void CheckServerDirectories() {
        Utils_.CheckAndCleanDirectory(TempDirectory = new File(Utils_.getHomeDirectory(), Constants.TempDirectoryName));
        Utils_.CheckDirectory(ComponentsDirectory = new File(Utils_.getHomeDirectory(), Constants.ComponentsDirectoryName));
        Utils_.CheckDirectory(DataDirectory = new File(Utils_.getHomeDirectory(), Constants.DataDirectoryName));
        Utils_.CheckDirectory(DataBackUpsDirectory = new File(Utils_.getHomeDirectory(), Constants.DataBackUpsDirectoryName));
        //--
        Utils_.CheckDirectory(BugReportsDirectory = new File(Utils_.getHomeDirectory(), "BugReports"));
        Utils_.CheckDirectory(KeysDirectory = new File(Utils_.getHomeDirectory(), Constants.KeyDirectoryName));
    }
    public static void CheckTestingSystemDirectories() {
        Utils_.CheckAndCleanDirectory(TempDirectory = new File(Utils_.getHomeDirectory(), Constants.TempDirectoryName));
        Utils_.CheckDirectory(DataDirectory = new File(Utils_.getHomeDirectory(), Constants.DataDirectoryName));
        Utils_.CheckDirectory(DataBackUpsDirectory = new File(Utils_.getHomeDirectory(), Constants.DataBackUpsDirectoryName));
        //-
        Utils_.CheckDirectory(TestsDirectory = new File(Utils_.getHomeDirectory(), Constants.TestsDirectoryName));
        Utils_.CheckDirectory(RepoDirectory = new File(Utils_.getHomeDirectory(), Constants.RepoDirectoryName));
        Utils_.CheckDirectory(DVMPackagesDirectory = new File(Utils_.getHomeDirectory(), Constants.DVMPackagesDirectoryName));
        Utils_.CheckDirectory(SapforsDirectory = new File(Utils_.getHomeDirectory(), "Sapfors"));
        Utils_.CheckDirectory(SapforPackagesDirectory = new File(Utils_.getHomeDirectory(), "SapforPackages"));
        Utils_.CheckDirectory(MachinesDirectory = new File(Utils_.getHomeDirectory(), "Machines"));
    }
    public static void CreateLogAtComponentsPath() {
        Utils_.MainLog = new Loggable() {
            @Override
            public String getLogHomePath() {
                return Paths.get(System.getProperty("user.dir"), "Components").toString();
            }
            @Override
            public String getLogName() {
                return "VisualDVM";
            }
        };
        Utils_.MainLog.ClearLog();
    }
    public static void CreateLogAtHome() {
        Utils_.MainLog = new Loggable() {
            @Override
            public String getLogHomePath() {
                return Utils_.getHomePath();
            }
            @Override
            public String getLogName() {
                return mode.toString();
            }
        };
        Utils_.MainLog.ClearLog();
    }
    //-
    public static void FinishApplication() {
        try {
            mainModule.DeactivateDB();
            if (componentsServer.db != null)
                componentsServer.db.Disconnect();
            if (componentsServer.credentials_db != null)
                componentsServer.credentials_db.Disconnect();
            if (testingServer.db != null)
                testingServer.db.Disconnect();
            if (visualizer_2 != null)
                visualizer_2.Shutdown();
            if (messagesServer != null)
                messagesServer.Shutdown();
            if (performanceAnalyzer != null)
                performanceAnalyzer.Shutdown();
        } catch (Exception ex) {
            if (Utils_.MainLog != null) {
                Utils_.MainLog.PrintException(ex);
            } else {
                ex.printStackTrace();
            }
        }
        System.exit(0);
    }
    //--
    public static void NormalMode(int port) throws Exception {
        //-------------------------------->>
        mainModule = new MainModule();
        System.out.println("main module initialization..");
        mainModule.Init();
        System.out.println("DONE");
        //--
        CheckVisualiserDirectories();
        CreateLogAtComponentsPath();
        //-
        System.out.println("connection to visualiser_2..");
        visualizer_2 = new Visualizer_2(port);
        visualizer_2.Connect();
        System.out.println("DONE");
        visualizer_2.refreshPid();
        //если делать раньше, то не удастся убить сервер.
        if (Utils_.ContainsCyrillic(Utils_.getHomePath())) {
            UI.Info("В пути к корневой папке " + Utils_.DQuotes(Utils_.getHomePath()) + "\n" +
                    "Найдены русские буквы.\n" +
                    "Визуализатор завершает работу."); //
            FinishApplication();
        }
        System.out.println("messages server starting..");
        messagesServer = new MessagesServer();
        messagesServer.Start();
        System.out.println("DONE");
        components = new ComponentsSet();
        System.out.println("component initial versions checking..");
        components.initialVersionsCheck();
        System.out.println("DONE");
        System.out.println("geting component actual versions..");
        Global.mainModule.getPass(PassCode.GetComponentsActualVersions).Do();
        System.out.println("DONE");
        System.out.println("validation component actual versions..");
        components.validateStates();
        System.out.println("DONE");
        if (components.needChanges()) {
            System.out.println("components need changes!!");
            boolean flag = true;
            do {
                System.out.println("Show components window...");
                Global.mainModule.getUI().getComponentsWindow().ShowDialog("");
                System.out.println("DONE");
                if (flag = (!components.validateStates())) {
                    if (!UI.Question("Обнаружены некорректные компоненты.Работа визуализатора невозможна.\n" +
                            "Вернуться к окну компонент"
                    )) {
                        UI.Info("Визуализатор завершает работу.");
                        FinishApplication();
                    }
                }
            } while (flag);
        }
        //--
        //-
        mainModule.set(Current.ProjectView, ProjectView.Files);
        AbstractTokenMakerFactory atmf = (AbstractTokenMakerFactory) TokenMakerFactory.getDefaultInstance();
        atmf.putMapping("text/FortranSPF", "_VisualDVM.Visual.Syntax.FortranSPFTokenMaker");
        atmf.putMapping("text/FreeFortranSPF", "_VisualDVM.Visual.Syntax.FreeFortranSPFTokenMaker");
        //  FoldParserManager.get().addFoldParserMapping("text/FortranSPF", new FortranFolder()); блоки кода. todo
        //light_editor.xml-------->>
        mainModule.ActivateDB();
        //   https://habr.com/ru/articles/446888/ сертификат?
        if (Global.normalProperties.OfferRegistrationOnStart)
            mainModule.getPass(PassCode.CheckAccount).Do();
        //---------------
        componentsServer.ActivateDB();
        testingServer.ActivateDB();
        //-- чисто чтобы создать таблицы. соединения на стороне клиента не предвидится.
        if (normalProperties.AutoBugReportsLoad)
            Global.mainModule.getPass(PassCode.SynchronizeBugReports).Do();
        if (normalProperties.AutoTestsLoad)
            Global.mainModule.getPass(PassCode.SynchronizeTests).Do();
        Global.mainModule.getPass(PassCode.SynchronizeCredentials).Do();
        //--
        Global.mainModule.getSapfor().refreshPid(); //без сапфора сюда это все равно не дойдет.
        Global.mainModule.getUI().getMainWindow().Show();
    }
    public static void ServerMode() throws Exception {
        CheckServerDirectories();
        CreateLogAtHome();
        componentsServer = new ComponentsServer();
        componentsServer.ActivateDB();
        componentsServer.Start();
        System.exit(0);
    }
    public static void TestingSystemMode() throws Exception {
        CheckTestingSystemDirectories();
        CreateLogAtHome();
        testingServer = new TestingServer();
        testingServer.ActivateDB();
        testingServer.Start();
        System.exit(0);
    }
    //режим запуска пакета Сапфор
    public static void PackageMode() throws Exception {
        CreateLogAtHome();
        PackageModeSupervisor planner = new PackageModeSupervisor();
        planner.Start();
    }
    public static void MachineQueueMode(String... args) throws Exception {
        RemoteDVMTestingPlanner supervisor = new RemoteDVMTestingPlanner(args);
        while (true) {
            supervisor.Perform();
        }
    }
    //---
    public static void SynchronizeProperties() throws Exception {
        File propertiesFile = new File(System.getProperty("user.dir"), "properties");
        if (!propertiesFile.exists()) {
            mode = Mode.Normal;
            properties = normalProperties = Utils_.SynschronizeProperties(propertiesFile, NormalProperties.class);
        } else {
            properties = Utils_.jsonFromFile(propertiesFile, VisualDVMProperties.class);
            mode = properties.Mode;
            //--->>
            switch (mode) {
                case Normal:
                    normalProperties = Utils_.SynschronizeProperties(propertiesFile, NormalProperties.class);
                    break;
                case Server:
                    componentsServerProperties = Utils_.SynschronizeProperties(propertiesFile, ComponentsServerProperties.class);
                    break;
                case Testing:
                    testingServerProperties = Utils_.SynschronizeProperties(propertiesFile, TestingServerProperties.class);
                    break;
                case MachineQueue:
                case Package:
                    break;
                default:
                    break;
            }
        }
    }
    //---
    public static void Init(String... args) {
        System.out.println("VisualSapfor.jar started..");
        System.out.println("home directory is" + Utils_.Brackets(Utils_.getHomePath()));
        System.out.println("args size = " + args.length);
        for (int i = 0; i < args.length; ++i)
            System.out.println("args[" + i + "]=" + Utils_.DQuotes(args[i]));
        System.out.println("====");
        //--->
        try {
            SynchronizeProperties();
            System.out.println("mode is " + mode);
            switch (mode) {
                case Normal:
                    NormalMode(Integer.parseInt(args[1]));
                    break;
                case Server:
                    ServerMode();
                    break;
                case Testing:
                    TestingSystemMode();
                    break;
                case Package:
                    PackageMode();
                    break;
                case MachineQueue:
                    MachineQueueMode(args);
                    break;
                case Undefined:
                    break;
            }
        } catch (Exception ex) {
            System.out.println("VISUALISER FAILED");
            ex.printStackTrace();
            if (Utils_.MainLog != null)
                Utils_.MainLog.PrintException(ex);
            FinishApplication();
        }
    }
}
