package _VisualDVM.Visual.Windows;
import Common.CommonConstants;
import Common.Visual.Editor.Viewer;
import Common.Visual.FormWithSplitters;
import Common.Visual.Tables.DataTable;
import Common.Visual.Trees.TreeForm;
import Common.Visual.UI;
import _VisualDVM.Global;
import _VisualDVM.Passes.PassCode;
import _VisualDVM.ProjectData.Files.DBProjectFile;
import _VisualDVM.ProjectData.Files.UI.Editor.SPFEditor;
import _VisualDVM.ProjectData.LanguageName;
import _VisualDVM.ProjectData.SapforData.Arrays.UI.FileArraysTree;
import _VisualDVM.ProjectData.SapforData.FileObjectWithMessages;
import _VisualDVM.ProjectData.SapforData.Functions.UI.FileFunctionsTree;
import _VisualDVM.ProjectData.SapforData.Loops.UI.FileLoopsTree;
import _VisualDVM.Visual.Interface.FileWindow;
import _VisualDVM.Visual.Interface.SPFEditorInterface;
import _VisualDVM.Visual.Menus.FileMenuBar.FileMenuBar;
import com.sun.org.glassfish.gmbal.Description;
import org.fife.ui.rtextarea.RTextScrollPane;

import javax.swing.*;
import java.awt.*;
public class FileForm implements FileWindow, FormWithSplitters {
    //контролы в столбцах
    //https://stackoverflow.com/questions/7137786/how-can-i-put-a-control-in-the-jtableheader-of-a-jtable
    //todo _ временно
    public static int current_file_line = CommonConstants.Nan;
    private final Viewer compilationOutput;
    private final Viewer runOutput;
    private final Viewer gcovLog;
    private final DBProjectFile file;
    //-
    public JSplitPane SC1;
    public JSplitPane SC12;
    @Description("IGNORE")
    protected boolean events_on = true;
    FileMenuBar fileMenuBar = null;
    //-
    private JPanel content;
    private JButton bClose;
    private JToolBar Tools;
    private JPanel editorPanel;
    private JTabbedPane messagesTabs;
    private JPanel notesPanel;
    private JPanel warningsPanel;
    private JPanel errorsPanel;
    private JTabbedPane graphsTabs;
    private JPanel loopsGraphPanel;
    private JPanel functionsGraphPanel;
    private JPanel arraysGraphPanel;
    private JPanel gcov_log_panel;
    private JPanel compilation_out_panel;
    private JPanel run_out_panel;
    //---------------->
    private JPanel recommendationsPanel;
    private JPanel graphsBackground;
    private JPanel messagesBackground;
    private JPanel editorBackground;
    //--------------->
    //-
    private TreeForm loopsForm; //рудиментарно. следует сделать интерфейс такой же как у таблиц
    private TreeForm functionsForm;
    private TreeForm arraysForm;
    //-
    private SPFEditor Body = null; //времянка? не очень красиво.
    //-
    public FileForm(DBProjectFile file_in) {
        LoadSplitters();
        //--
        file = file_in;
        //--
        loopsForm = new TreeForm(FileLoopsTree.class, loopsGraphPanel);
        functionsForm = new TreeForm(FileFunctionsTree.class, functionsGraphPanel);
        arraysForm = new TreeForm(FileArraysTree.class, arraysGraphPanel);
        //--
        file.father.db.notes.mountUI(notesPanel);
        file.father.db.warnings.mountUI(warningsPanel);
        file.father.db.errors.mountUI(errorsPanel);
        file.father.db.recommendations.mountUI(recommendationsPanel);
        //---------------------------------------------------------------------------
        compilation_out_panel.add(new JScrollPane(compilationOutput = new Viewer()));
        run_out_panel.add(new JScrollPane(runOutput = new Viewer()));
        gcov_log_panel.add(new JScrollPane(gcovLog = new Viewer()));
        //----------------------------------------------------------------------------
        ShowText();
        ShowMessages();
        ShowGCOVLog();
        ShowAllAnalyses();
        Body.addCaretListener(ce -> ShowCaretInfo());
        editorPanel.add(fileMenuBar = new FileMenuBar(Body), BorderLayout.NORTH);
        ShowCaretInfo();
        Body.requestFocus();
        RefreshTabsNames();
        fileMenuBar.sToGo.addChangeListener(e -> Body.gotoLine((Integer) fileMenuBar.sToGo.getValue()));
        ShowProperties();
        Global.mainModule.getPass(PassCode.Save).setControlsEnabled(false);
        //-
        if (Global.normalProperties.collapseFileGraphs)
            CollapseGraphs();
        //-
        if (Global.normalProperties.collapseFileMessages)
            CollapseMessages();
    }
    @Override
    public void ShowLanguage() {
        Body.switching_language = true;
        if (file.languageName.equals(LanguageName.fortran)) {
            switch (file.style) {
                case fixed:
                case extended:
                case none:
                    Body.setSyntaxEditingStyle("text/FortranSPF");
                    break;
                case free:
                    Body.setSyntaxEditingStyle("text/FreeFortranSPF");
                    break;
            }
        } else
            Body.setSyntaxEditingStyle(file.languageName.getStyleKey());
        Body.setCodeFoldingEnabled(true);
        Body.switching_language = false;
        fileMenuBar.ShowLanguage();
    }
    @Override
    public void ShowType() {
        fileMenuBar.ShowType();
    }
    @Override
    public void ShowStyle() {
        Body.switching_language = true;
        int m = file.style.getMargin();
        Body.setMarginLineEnabled(true);
        Body.setMarginLinePosition(m);
        if (m <= 0)
            Body.setMarginLineEnabled(false);
        if (file.languageName.equals(LanguageName.fortran)) {
            switch (file.style) {
                case fixed:
                case extended:
                case none:
                    Body.setSyntaxEditingStyle("text/FortranSPF");
                    break;
                case free:
                    Body.setSyntaxEditingStyle("text/FreeFortranSPF");
                    break;
            }
        }
        Body.switching_language = false;
        fileMenuBar.ShowStyle();
    }
    @Override
    public SPFEditorInterface getEditor() {
        return Body;
    }
    @Override
    public void FocusLoops() {
        graphsTabs.setSelectedIndex(0);
    }
    @Override
    public void FocusFunctions() {
        graphsTabs.setSelectedIndex(1);
    }
    @Override
    public void FocusArrays() {
        graphsTabs.setSelectedIndex(2);
    }
    //----
    @Override
    public void ShowWarningsCount() {
        messagesTabs.setTitleAt(1, (Global.normalProperties.ShowFullTabsNames ? "Предупреждения: " : "") + file.father.db.warnings.getUI().getRowCount());
    }
    @Override
    public void ShowErrorsCount() {
        messagesTabs.setTitleAt(2, (Global.normalProperties.ShowFullTabsNames ? "Ошибки: " : "") + file.father.db.errors.getUI().getRowCount());
    }
    @Override
    public void ShowNotesCount() {
        messagesTabs.setTitleAt(0, (Global.normalProperties.ShowFullTabsNames ? "Примечания: " : "") + file.father.db.notes.getUI().getRowCount());
    }
    @Override
    public void ShowRecommendationsCount() {
        messagesTabs.setTitleAt(3, (Global.normalProperties.ShowFullTabsNames ? "Рекомендации: " : "") + file.father.db.recommendations.getUI().getRowCount());
    }
    //---
    @Override
    public void RefreshTabsNames() {
        UI.ShowTabsNames(graphsTabs, Global.normalProperties.ShowFullTabsNames);
        //--
        ShowNotesCount();
        ShowWarningsCount();
        ShowErrorsCount();
        ShowRecommendationsCount();
        //--
        messagesTabs.setTitleAt(4, (Global.normalProperties.ShowFullTabsNames ? "Компиляция" : ""));
        messagesTabs.setTitleAt(5, (Global.normalProperties.ShowFullTabsNames ? "Запуск" : ""));
        messagesTabs.setTitleAt(6, (Global.normalProperties.ShowFullTabsNames ? "Журнал GCOV" : ""));
    }
    @Override
    public void FocusCompilationOut() {
        messagesTabs.setSelectedIndex(4);
    }
    @Override
    public void FocusCompilationErrors() {
        messagesTabs.setSelectedIndex(5);
    }
    @Override
    public void ShowText() {
        UI.Clear(editorPanel);
        editorPanel.add(new RTextScrollPane(Body = new SPFEditor(file)));
        Global.mainModule.getUI().getSearchReplaceWindow().updateEditor(Body);
    }
    @Override
    public void ShowMessages() {
        ShowMessages(null);
    }
    @Override
    public void ShowMessages(FileObjectWithMessages graphElement) {
        file.father.db.notes.ShowUI();
        file.father.db.warnings.ShowUI();
        file.father.db.errors.ShowUI();
        file.father.db.recommendations.ShowUI();
        ShowNotesCount();
        ShowWarningsCount();
        ShowErrorsCount();
        ShowRecommendationsCount();
        //-
        FocusMessagesPriority(graphElement == null ? file.state.toString() : graphElement.messages_presence);
    }
    @Override
    public void ShowNoMessages() {
        file.father.db.notes.ClearUI();
        file.father.db.warnings.ClearUI();
        file.father.db.errors.ClearUI();
        file.father.db.recommendations.ClearUI();
        messagesTabs.setTitleAt(0, (Global.normalProperties.ShowFullTabsNames ? "Примечания: " : "") + "-");
        messagesTabs.setTitleAt(1, (Global.normalProperties.ShowFullTabsNames ? "Предупреждения: " : "") + "-");
        messagesTabs.setTitleAt(2, (Global.normalProperties.ShowFullTabsNames ? "Ошибки: " : "") + "-");
        messagesTabs.setTitleAt(3, (Global.normalProperties.ShowFullTabsNames ? "Рекомендации: " : "") + "-");
    }
    @Override
    public void ShowLoops() {
        loopsForm.Show();
        Body.HighlightLoops();
    }
    @Override
    public void ShowNoLoops() {
        loopsForm.Clear();
        Body.ClearLoopsHighLights();
    }
    @Override
    public void ShowGCOVLog() {
        gcovLog.setText(file.GCOVLog);
    }
    @Override
    public void ShowGCOV() {
        Body.HighlightGCOV();
    }
    @Override
    public void ShowNoGCOVLog() {
        gcovLog.setText("");
    }
    @Override
    public void FocusGCOVLog() {
        messagesTabs.setSelectedIndex(6);
    }
    @Override
    public void ShowNoGCOV() {
        Body.ClearGOCVHighlights();
    }
    @Override
    public void ShowFunctions() {
        functionsForm.Show();
    }
    @Override
    public void ShowNoFunctions() {
        functionsForm.Clear();
    }
    @Override
    public void ShowArrays() {
        arraysForm.Show();
    }
    @Override
    public void ShowNoArrays() {
        arraysForm.Clear();
    }
    public void EventsOn() {
        events_on = true;
    }
    public void EventsOff() {
        events_on = false;
    }
    @Override
    public void ShowCaretInfo() {
        int new_current_line = Body.getCurrentLine();
        boolean line_changed = (new_current_line != current_file_line);
        current_file_line = new_current_line;
        fileMenuBar.sToGo.setModel(new SpinnerNumberModel(current_file_line,
                1, Body.getLineCount(), 1
        ));
        //-
        fileMenuBar.ShowLinesCount();
        fileMenuBar.CurrentSymbolLabel.setText(String.valueOf(Body.getCurrentSymbol()));
        //если выделяем строку из графа, то тоже надо отключиьт события.
        //чтобы по ней не начался поиск.
        if (events_on && line_changed) {
            if (loopsForm.getTree() != null)
                loopsForm.getTree().SelectNodeByCriteria(current_file_line);
            if (functionsForm.getTree() != null)
                functionsForm.getTree().SelectNodeByCriteria(current_file_line);
            if (arraysForm.getTree() != null)
                arraysForm.getTree().SelectNodeByCriteria(current_file_line);
        }
    }
    @Override
    public void FocusMessagesPriority(String messages_presence) {
        switch (messages_presence) {
            case "HasErrors":
                messagesTabs.setSelectedIndex(2);
                break;
            case "HasWarnings":
                messagesTabs.setSelectedIndex(1);
                break;
            case "HasNotes":
                messagesTabs.setSelectedIndex(0);
                break;
            default:
                messagesTabs.setSelectedIndex(0);
                break;
        }
    }
    @Override
    public void ShowFirstError() {
        if (file.father.db.errors.getUI().getRowCount() > 0)
            ((DataTable) file.father.db.errors.getUI().getControl()).SelectRow(0);
    }
    @Override
    public void ShowCompilationOutput() {
        compilationOutput.setText(file.father.compilation_output);
    }
    @Override
    public void ShowNoCompilationOutput() {
        compilationOutput.setText("");
    }
    @Override
    public void ShowRunOutput() {
        runOutput.setText(file.father.run_output);
    }
    @Override
    public void ShowNoRunOutput() {
        runOutput.setText("");
    }
    @Override
    public JPanel getContent() {
        return content;
    }
    //--
    @Override
    public void CollapseGraphs() {
        Global.mainModule.getDb().splitters.get("SC12").position = SC12.getDividerLocation();
        UI.Clear(editorBackground);
        editorBackground.add(editorPanel);
    }
    @Override
    public void ExpandGraphs() {
        UI.Clear(editorBackground);
        SC12.setRightComponent(editorPanel);
        editorBackground.add(SC12);
        //--
        SC12.setDividerLocation(Global.mainModule.getDb().splitters.get("SC12").position);
        SC12.updateUI();
    }
    @Override
    public void CollapseMessages() {
        Global.mainModule.getDb().splitters.get("SC1").position = SC1.getDividerLocation();
        UI.Clear(content);
        content.add(editorBackground);
    }
    @Override
    public void ExpandMessages() {
        UI.Clear(content);
        SC1.setLeftComponent(editorBackground);
        content.add(SC1);
        SC1.setDividerLocation(Global.mainModule.getDb().splitters.get("SC1").position);
        SC1.updateUI();
    }
}
