package Common.UI;
import Common.Current;
import Common.Database.DataSet;
import Common.Global;
import Repository.BugReport.BugReportsMenuBar;
import GlobalData.Compiler.CompilersMenuBar;
import TestingSystem.DVM.Configuration.ConfigurationsMenuBar;
import TestingSystem.DVM.DVMPackage.DVMPackagesBar;
import GlobalData.DVMParameter.DVMParametersMenuBar;
import Common.UI.Menus_2023.DataMenuBar;
import GlobalData.EnvironmentValue.EnvironmentValuesMenuBar;
import Common.UI.Menus_2023.FastAccessMenuBar.FastAccessMenuBar;
import TestingSystem.Common.Group.GroupsMenuBar;
import GlobalData.Machine.MachinesMenuBar;
import Common.UI.Menus_2023.MainMenuBar.MainMenuBar;
import Common.UI.Menus_2023.MainMenuBar.MainWindow;
import GlobalData.Makefile.MakefilesMenuBar;
import GlobalData.Module.ModulesMenuBar;
import GlobalData.RunConfiguration.RunConfigurationsMenuBar;
import TestingSystem.DVM.DVMTasks.DVMRunTasksBar;
import TestingSystem.DVM.DVMTasks.DVMRunTasksSet;
import TestingSystem.SAPFOR.SapforConfigurationCommand.SapforConfigurationCommandsMenuBar;
import TestingSystem.SAPFOR.SapforConfiguration.SapforConfigurationsMenuBar;
import TestingSystem.SAPFOR.ServerSapfor.ServerSapforsBar;
import Repository.SubscriberWorkspace.SubscriberWorkspacesMenuBar;
import Repository.Subscribes.SubscribersMenuBar;
import TestingSystem.Common.TestingBar;
import TestingSystem.Common.Test.TestsMenuBar;
import GlobalData.User.UsersMenuBar;
import Common.UI.Menus_2023.VariantsMenuBar.VariantsMenuBar;
import Common.UI.Menus_2023.VersionsMenuBar.VersionsMenuBar;
import Common.UI.Tables.*;
import Common.UI.Themes.*;
import Common.UI.Trees.GraphTreeCellRenderer;
import Common.UI.Trees.SelectionTreeCellRenderer;
import Common.UI.Windows.FormType;
import Common.UI.Windows.SearchReplaceForm;
import Common.Utils.Utils;
import GlobalData.Compiler.CompilersDBTable;
import GlobalData.CompilerEnvironment.UI.CompilerEnvironmentValueEditor;
import GlobalData.CompilerEnvironment.UI.CompilerEnvironmentValueRenderer;
import GlobalData.CompilerOption.UI.CompilerOptionParameterNameRenderer;
import GlobalData.CompilerOption.UI.CompilerOptionParameterValueEditor;
import GlobalData.CompilerOption.UI.CompilerOptionParameterValueRenderer;
import GlobalData.DVMParameter.DVMParameterDBTable;
import GlobalData.EnvironmentValue.EnvironmentValuesDBTable;
import GlobalData.Machine.MachinesDBTable;
import GlobalData.Makefile.MakefilesDBTable;
import GlobalData.Module.ModulesDBTable;
import GlobalData.RemoteFile.UI.RemoteFileChooser;
import GlobalData.RemoteFile.UI.RemoteFileRenderer;
import GlobalData.RunConfiguration.RunConfigurationsDBTable;
import GlobalData.SapforProfile.SapforProfilesDBTable;
import GlobalData.Settings.SettingName;
import GlobalData.Tasks.CompilationTask.CompilationTasksDBTable;
import GlobalData.Tasks.RunTask.RunTasksDBTable;
import GlobalData.User.UsersDBTable;
import ProjectData.DBArray.ArraysDBTable;
import ProjectData.Files.UI.FilesTreeCellRenderer;
import Repository.SubscriberWorkspace.SubscriberWorkspaceDBTable;
import TestingSystem.DVM.DVMPackage.DVMPackageDBTable;
import TestingSystem.SAPFOR.SapforPackage.SapforPackageDBTable;
import TestingSystem.SAPFOR.SapforPackage.SapforPackagesBar;
import TestingSystem.SAPFOR.SapforTasksPackage.UI.SapforVersionsTreeCellRenderer;
import ProjectData.Project.UI.VersionsTreeCellRenderer;
import ProjectData.SapforData.Arrays.ArraysSet;
import ProjectData.SapforData.Arrays.UI.DimensionRenderer;
import ProjectData.SapforData.Arrays.UI.DimensionStateChanger;
import ProjectData.SapforData.Arrays.UI.RulesTreeCellRenderer;
import ProjectData.SapforData.Regions.RegionsSet;
import ProjectData.SapforData.Variants.UI.VariantRankRenderer;
import ProjectData.SapforData.Variants.VariantsSet;
import Repository.BugReport.BugReportsDBTable;
import Repository.Component.UI.ComponentsForm;
import Repository.Subscribes.SubsribersDBTable;
import TestingSystem.SAPFOR.SapforConfiguration.SapforConfigurationDBTable;
import TestingSystem.SAPFOR.SapforConfigurationCommand.SapforConfigurationCommandsDBTable;
import TestingSystem.SAPFOR.ServerSapfor.ServerSapforsDBTable;
import TestingSystem.DVM.Configuration.ConfigurationDBTable;
import TestingSystem.Common.Group.GroupsDBTable;
import TestingSystem.Common.Test.TestDBTable;
import Visual_DVM_2021.Passes.PassCode_2021;
import Visual_DVM_2021.UI.Interface.DebugWindow;
import Visual_DVM_2021.UI.Interface.VersionsWindow;
import Visual_DVM_2021.UI.Main.*;

import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
import javax.swing.*;
import javax.swing.event.ChangeListener;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.text.DefaultFormatter;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.Highlighter;
import javax.swing.tree.TreeCellRenderer;
import java.awt.*;
import java.util.LinkedHashMap;
import java.util.Stack;
import java.util.Vector;

import static Common.UI.Tables.TableEditors.*;
import static Common.UI.Tables.TableRenderers.*;
import static Common.UI.Trees.TreeRenderers.*;
public class UI {
    public static MenuElement[] last_menu_path;
    public static MainMenuBar mainMenuBar = null;
    public static TestingBar testingBar = null;
    public static VersionsMenuBar versionsMenuBar = null;
    public static FastAccessMenuBar fastAccessMenuBar = null;
    //------------
    public static VersionsWindow versionsWindow = null;
    public static DebugWindow debugWindow = null;
    //------------
    public static final Highlighter.HighlightPainter GoodLoopPainter = new DefaultHighlighter.DefaultHighlightPainter(new Color(152, 251, 152, 90));
    public static final Highlighter.HighlightPainter BadLoopPainter = new DefaultHighlighter.DefaultHighlightPainter(new Color(240, 128, 128, 90));
    public static LinkedHashMap<Common.UI.Tables.TableRenderers, TableCellRenderer> TableRenderers = new LinkedHashMap<>();
    public static LinkedHashMap<Common.UI.Tables.TableEditors, TableCellEditor> TableEditors = new LinkedHashMap<>();
    public static LinkedHashMap<Common.UI.Trees.TreeRenderers, TreeCellRenderer> TreeRenderers = new LinkedHashMap<>();
    public static LinkedHashMap<VisualiserThemeName, VisualiserTheme> themes = new LinkedHashMap<>();
    public static LinkedHashMap<FormType, ThemeElement> windows = new LinkedHashMap<>();
    public static Stack<Component> windowsStack = new Stack<>();
    //-----
    public static LinkedHashMap<Class, DataMenuBar> menuBars = new LinkedHashMap<>();
    //-----
    public static void Clear(Container container) {
        container.removeAll();
        container.repaint();
        container.revalidate();
    }
    // http://java-online.ru/swing-joptionpane.xhtml
    public static <T> void TrySelect(JComboBox box, T value_in) {
        if (value_in != null) {
            for (int i = 0; i < box.getItemCount(); ++i) {
                T value = (T) box.getItemAt(i);
                if (value.equals(value_in)) {
                    box.setSelectedIndex(i);
                    return;
                }
            }
            box.addItem(value_in);
            box.setSelectedIndex(box.getItemCount() - 1);
        }
    }
    public static void TrySelect_s(JComboBox box, String value_string_in) {
        for (int i = 0; i < box.getItemCount(); ++i) {
            Object value = box.getItemAt(i);
            if (value.toString().equals(value_string_in)) {
                box.setSelectedIndex(i);
                return;
            }
        }
    }
    public static RemoteFileChooser getRemoteFileChooser() {
        return (RemoteFileChooser) windows.get(FormType.RemoteFileChooser);
    }
    public static ComponentsForm getComponentsWindow() {
        return (ComponentsForm) windows.get(FormType.Components);
    }
    public static boolean HasMainWindow() {
        return getMainWindow() != null;
    }
    public static SearchReplaceForm getSearchReplaceForm() {
        return (SearchReplaceForm) windows.get(FormType.SearchReplace);
    }
    public static void refreshTheme() {
        Current.set(Current.Theme, themes.get(Global.db.settings.get(SettingName.DarkThemeOn).toBoolean() ? VisualiserThemeName.Dark : VisualiserThemeName.Light));
        // refreshTheme_r(Visualiser.getMainWindow().MainPanel);
        /*
        refreshTheme_r(Visualiser.searchReplaceForm.MainPanel);
        refreshTheme_r(Visualiser.ComponentsWindow.fields.MainPanel);
        refreshTheme_r(Visualiser.remoteFileChooser.fields.MainPanel);
        refreshTheme_r(Visualiser.runStatisticForm.fields.MainPanel);
        //-----------------------------------------------------------------

        UIManager.put("ToolTip.background", Current.getTheme().background);
        UIManager.put("ToolTip.foreground", Current.getTheme().foreground);
        UIManager.put("Panel.background", Current.getTheme().background);
        UIManager.put("Panel.foreground", Current.getTheme().foreground);

        UIManager.put("TextPane.background", Current.getTheme().background);
        UIManager.put("TextPane.foreground", Current.getTheme().foreground);

        UIManager.put("Label.background", Current.getTheme().background);
        UIManager.put("Label.foreground", Current.getTheme().foreground);

        UIManager.put("ToolBar.background", Current.getTheme().background);
        UIManager.put("ToolBar.foreground", Current.getTheme().foreground);

        for (TableCellRenderer renderer : TableRenderers.values()) {
            if (renderer instanceof WindowControl) {
                ((WindowControl) renderer).applyTheme();
            }
        }
        for (TreeCellRenderer renderer : TreeRenderers.values()) {
            if (renderer instanceof WindowControl) {
                ((WindowControl) renderer).applyTheme();
            }
        }
        //для текущего файла отдельно
        ///  if (Current.HasFile())
        //     Current.getFile().form.Body.applyTheme();
        //------------
        //  UIManager.put("TabbedPane.unselectedForeground", Color.red);
        //  UIManager.put("TabbedPane.selectedBackground", Color.black);
        //----------------------------
         */
    }
    public static void CreateMenus() {
        mainMenuBar = new MainMenuBar();
        testingBar = new TestingBar();
        versionsMenuBar = new VersionsMenuBar();
        fastAccessMenuBar = new FastAccessMenuBar();
        //---------------------------------------------------->>
        menuBars.put(BugReportsDBTable.class, new BugReportsMenuBar());
        menuBars.put(SubscriberWorkspaceDBTable.class, new SubscriberWorkspacesMenuBar());
        //---------------------------------------------------->>
        menuBars.put(GroupsDBTable.class, new GroupsMenuBar());
        menuBars.put(TestDBTable.class, new TestsMenuBar());
        menuBars.put(ConfigurationDBTable.class, new ConfigurationsMenuBar());
        menuBars.put(DVMPackageDBTable.class, new DVMPackagesBar());
        menuBars.put(SapforPackageDBTable.class, new SapforPackagesBar());
        menuBars.put(DVMRunTasksSet.class, new DVMRunTasksBar());
        //--->>>
        menuBars.put(MachinesDBTable.class, new MachinesMenuBar());
        menuBars.put(UsersDBTable.class, new UsersMenuBar());
        menuBars.put(CompilersDBTable.class, new CompilersMenuBar());
        menuBars.put(MakefilesDBTable.class, new MakefilesMenuBar());
        menuBars.put(ModulesDBTable.class, new ModulesMenuBar());
        menuBars.put(RunConfigurationsDBTable.class, new RunConfigurationsMenuBar());
        menuBars.put(EnvironmentValuesDBTable.class, new EnvironmentValuesMenuBar());
        menuBars.put(DVMParameterDBTable.class, new DVMParametersMenuBar());
        menuBars.put(CompilationTasksDBTable.class, new DataMenuBar("задачи на компиляцию"));
        menuBars.put(RunTasksDBTable.class, new DataMenuBar("задачи на запуск"));
        //---->>
        menuBars.put(SapforConfigurationDBTable.class, new SapforConfigurationsMenuBar());
        menuBars.put(SapforConfigurationCommandsDBTable.class, new SapforConfigurationCommandsMenuBar());
        //---->>
        menuBars.put(RegionsSet.class, new DataMenuBar("области распараллеливания"));
        menuBars.put(ArraysSet.class, new DataMenuBar("массивы"));
        menuBars.put(ArraysDBTable.class, new DataMenuBar("сохранённые состояния") {
            @Override
            public void createSelectionButtons(DataSet dataSet) {
                //не нужны.
            }
        });
        menuBars.put(VariantsSet.class, new VariantsMenuBar());
        menuBars.put(SubsribersDBTable.class, new SubscribersMenuBar());
        menuBars.put(SapforProfilesDBTable.class, new DataMenuBar("профили", PassCode_2021.SaveProfile, PassCode_2021.EditProfile, PassCode_2021.ApplyProfile, PassCode_2021.DeleteProfile));
        menuBars.put(ServerSapforsDBTable.class, new ServerSapforsBar());
        //---->>
    }
    public static void CreateWindows() {
        windows.put(FormType.SearchReplace, new SearchReplaceForm());
        windows.put(FormType.RemoteFileChooser, new RemoteFileChooser());
        windows.put(FormType.Profiles, new ProfilesForm());
        windows.put(FormType.Main, new MainForm());
        //---------------------------------------
        getMainWindow().Show();
    }
    public static MainWindow getMainWindow() {
        return (MainWindow) windows.get(FormType.Main);
    }
    //-
    public static void CreateAll() {
        //<editor-fold desc="Локализация компонентов окна JFileChooser">
        UIManager.put(
                "FileChooser.openButtonText", "Открыть");
        UIManager.put(
                "FileChooser.saveButtonText", "Сохранить");
        UIManager.put(
                "FileChooser.cancelButtonText", "Отмена");
        UIManager.put(
                "FileChooser.fileNameLabelText", "Наименование файла");
        UIManager.put(
                "FileChooser.filesOfTypeLabelText", "Типы файлов");
        UIManager.put(
                "FileChooser.lookInLabelText", "Директория");
        UIManager.put(
                "FileChooser.saveInLabelText", "Сохранить в директории");
        UIManager.put(
                "FileChooser.folderNameLabelText", "Путь директории");
        //</editor-fold>
        //<editor-fold desc="Локализация компонентов окна подтверждения">
        UIManager.put("OptionPane.yesButtonText", "Да");
        UIManager.put("OptionPane.noButtonText", "Нет");
        UIManager.put("OptionPane.cancelButtonText", "Отмена");
        UIManager.put("OptionPane.okButtonText", "Готово");
        //</editor-fold>
        //<editor-fold desc="Темы(всегда создавать первыми)">
        themes.put(VisualiserThemeName.Light, new LightVisualiserTheme());
        themes.put(VisualiserThemeName.Dark, new DarkVisualiserTheme());
        //по умолчанию поставить светлую тему. потому что до загрузки бд работаем с таблицей компонент.
        Current.set(Current.Theme, themes.get(VisualiserThemeName.Light));
        //</editor-fold>
        //<editor-fold desc="Объекты отрисовки и редактирования деревьев и таблиц">
        TableRenderers.put(RendererDate, new DateRenderer_());
        TableRenderers.put(RendererProgress, new ProgressBarRenderer());
        TableRenderers.put(RendererSelect, new DBObjectSelectionRenderer());
        TableRenderers.put(RendererDimension, new DimensionRenderer());
        TableRenderers.put(RendererMultiline, new MultilineRenderer());
        TableRenderers.put(RendererHyperlinks, new HyperlinksRenderer());
        TableRenderers.put(RendererTopLeft, new TopLeftRenderer());
        TableRenderers.put(RendererMaskedInt, new MaskedIntegerValueRenderer());
        TableRenderers.put(RendererVariantRank, new VariantRankRenderer());
        TableRenderers.put(RendererHiddenList, new HiddenListRenderer());
        TableRenderers.put(RendererWrapText, new WrapTextRenderer());
        TableRenderers.put(RendererCompilerOptionParameterValue, new CompilerOptionParameterValueRenderer());
        TableRenderers.put(RendererCompilerOptionParameterName, new CompilerOptionParameterNameRenderer());
        TableRenderers.put(RendererCompilerEnvironmentValue, new CompilerEnvironmentValueRenderer());
        TableRenderers.put(RendererStatusEnum, new StatusEnumRenderer());
        //---------------------------------------------
        TreeRenderers.put(RendererGraph, new GraphTreeCellRenderer());
        TreeRenderers.put(RendererRemoteFile, new RemoteFileRenderer());
        TreeRenderers.put(RendererFile, new FilesTreeCellRenderer());
        TreeRenderers.put(RendererVersion, new VersionsTreeCellRenderer());
        TreeRenderers.put(RendererSapforVersion, new SapforVersionsTreeCellRenderer());
        TreeRenderers.put(RendererRule, new RulesTreeCellRenderer());
        TreeRenderers.put(RendererSelection, new SelectionTreeCellRenderer());
        //----------------------------------------------
        TableEditors.put(EditorSelect, new DBObjectSelector());
        TableEditors.put(EditorHyperlinks, new VectorEditor());
        TableEditors.put(EditorDimension, new DimensionStateChanger());
        TableEditors.put(EditorCompilerOptionParameterValue, new CompilerOptionParameterValueEditor());
        TableEditors.put(EditorCompilerEnvironmentValue, new CompilerEnvironmentValueEditor());
        //</editor-fold>
    }
    public static void printAccessible_r(Accessible accessible) {
        System.out.print(accessible.getClass().getSimpleName() + ": children_count: ");
        AccessibleContext context = accessible.getAccessibleContext();
        System.out.println(context.getAccessibleChildrenCount());
        for (int i = 0; i < context.getAccessibleChildrenCount(); ++i) {
            printAccessible_r(context.getAccessibleChild(i));
        }
    }
    public static void refreshTheme_r(Accessible accessible) {
        //  System.out.println(accessible.getClass().getSimpleName() + ": children_count: ");
        AccessibleContext context = accessible.getAccessibleContext();
        if (accessible instanceof ThemeElement) {
            // System.out.println(accessible.getClass().getSimpleName() + ": refresh theme");
            ((ThemeElement) accessible).applyTheme();
        } else {
            if ((accessible instanceof JPanel) ||
                    (accessible instanceof JLabel) ||
                    (accessible instanceof JToolBar) ||
                    (accessible instanceof JTabbedPane) ||
                    (accessible instanceof JScrollPane) ||
                    (accessible instanceof JSplitPane) ||
                    (accessible instanceof JTextField) ||
                    (accessible instanceof JCheckBox)
            ) {
            } else if (accessible instanceof JTextArea) {
                accessible.getAccessibleContext().getAccessibleComponent().setBackground(Current.getTheme().background);
                accessible.getAccessibleContext().getAccessibleComponent().setForeground(Current.getTheme().trees_background);
            }
        }
        for (int i = 0; i < context.getAccessibleChildrenCount(); ++i) {
            refreshTheme_r(context.getAccessibleChild(i));
        }
    }
    public static void CreateComponentsForm() {
        windows.put(FormType.Components, new ComponentsForm());
    }
    public static ProfilesForm getProfilesWindow() {
        return (ProfilesForm) windows.get(FormType.Profiles);
    }
    public static Component getFrontWindow() {
        Component res = null;
        try {
            res = windowsStack.peek();
        } catch (Exception ex) {
            System.out.println("NO FRONT WINDOW FOUND");
        }
        return res;
    }
    //-----
    public static void ShowTabsNames(JTabbedPane tabs) {
        ShowTabsNames(tabs, 0);
    }
    public static void ShowTabsNames(JTabbedPane tabs, int startIndex) {
        boolean flag = Global.db.settings.get(SettingName.ShowFullTabsNames).toBoolean();
        for (int i = startIndex; i < tabs.getTabCount(); ++i)
            tabs.setTitleAt(i, flag ? tabs.getToolTipTextAt(i) : "");
    }
    public static boolean Contains(Vector<String> list, String line, int max_index) {
        int last_index = -1;
        for (int i = 0; i < list.size(); ++i)
            if (list.get(i).equals(line)) last_index = i;
        return (last_index >= max_index);
    }
    public static void MakeSpinnerRapid(JSpinner spinner, ChangeListener listener) {
        JComponent comp = spinner.getEditor();
        JFormattedTextField field = (JFormattedTextField) comp.getComponent(0);
        DefaultFormatter formatter = (DefaultFormatter) field.getFormatter();
        formatter.setCommitsOnValidEdit(true);
        formatter.setAllowsInvalid(true);
        spinner.addChangeListener(listener);
    }
    //---------------
    public static boolean Question(Component parent, String text) {
        return !Current.hasUI() || (JOptionPane.showConfirmDialog(parent,
                text + "?",
                "Подтверждение",
                JOptionPane.YES_NO_OPTION,
                JOptionPane.QUESTION_MESSAGE) == 0);
    }
    public static boolean Question(String text) {
        return Question(getFrontWindow(), text);
    }
    public static void Info(String message) {
        Utils.CopyToClipboard(message);
        if (Current.hasUI())
            JOptionPane.showMessageDialog(getFrontWindow(), message, "", 1);
    }
    public static void Error(String message) {
        Utils.CopyToClipboard(message);
        if (Current.hasUI())
            JOptionPane.showMessageDialog(getFrontWindow(), message, "", 0);
    }
    public static boolean Warning(String text) {
        return !Current.hasUI() ||
                JOptionPane.showConfirmDialog(getFrontWindow(),
                        text + "\nВы уверены?",
                        "Подтверждение",
                        JOptionPane.YES_NO_OPTION,
                        JOptionPane.WARNING_MESSAGE) == 0;
    }
    //--
    public static VersionsWindow getVersionsWindow() {
        return versionsWindow;
    }
    public static void CreateVersionsWindow() {
        versionsWindow = new VersionsForm(Current.getRoot());
    }
    public static DebugWindow getDebugWindow() {
        if (debugWindow == null)
            debugWindow = new DebugForm();
        return debugWindow;
    }
    //-
    public static void ShowSearchForm(boolean replace) {
        getSearchReplaceForm().setMode(replace);
        getSearchReplaceForm().ShowMode();
        ShowSearchForm();
    }
    public static void HideSearchForm() {
        if (getSearchReplaceForm().isVisible())
            getSearchReplaceForm().setVisible(false);
    }
    public static void ShowSearchForm() {
        if (getSearchReplaceForm().isVisible())
            getSearchReplaceForm().Refresh();
        else
            getSearchReplaceForm().Show();
    }
    public static void ShowComponentsWindow() {
        getComponentsWindow().ShowDialog("");
    }
    public static void ShowProfilesWindow() {
        getProfilesWindow().ShowDialog("");
    }
}
