package _VisualDVM.ProjectData.Files.UI.Editor;
import Common.Utils.Pair;
import Common.Utils.Utils_;
import Common.Visual.Editor.BaseEditor;
import Common.Visual.Menus.StyledPopupMenu;
import _VisualDVM.Global;
import _VisualDVM.Passes.PassCode;
import _VisualDVM.ProjectData.Files.DBProjectFile;
import _VisualDVM.ProjectData.Files.FileState;
import _VisualDVM.ProjectData.Files.UI.Editor.AutoComplete.SAPFOR.SapforAutoComplete;
import _VisualDVM.ProjectData.SapforData.Loops.Loop;
import _VisualDVM.Utils;
import _VisualDVM.Visual.Editor.CaretInfo;
import _VisualDVM.Visual.Interface.SPFEditorInterface;
import _VisualDVM.Visual.Menus.MainEditorMenu;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextAreaHighlighter;

import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.Highlighter;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Vector;
public class SPFEditor extends BaseEditor implements SPFEditorInterface {
    public static final Color never = new Color(229, 228, 226, 90);
    //--
    public static final Highlighter.HighlightPainter GreenTextPainter = new DefaultHighlighter.DefaultHighlightPainter(new Color(152, 251, 152, 90));
    public static final Highlighter.HighlightPainter RedTextPainter = new DefaultHighlighter.DefaultHighlightPainter(new Color(240, 128, 128, 90));
    //</editor-fold>
    //------------------------------------------------------
    public static boolean enable_text_changed = false;
    public DBProjectFile file = null; //файл связанный с редактором
    //----
    public RSyntaxTextAreaHighlighter highlighter = null;
    //----
    public SapforAutoComplete autoComplete = null;
    public boolean switching_language = false;
    Vector<Object> loopsHighlights = new Vector<>();
    Vector<Object> gcovHighlights = new Vector<>();
    //-включение /отключение событий --
    private CaretInfo caretInfo = new CaretInfo();
    public SPFEditor(DBProjectFile file_in) {
        file = file_in;
        highlighter = (RSyntaxTextAreaHighlighter) getHighlighter();
        autoComplete = new SapforAutoComplete(this);
        //-------------------------
        float font_size = (float) Global.normalProperties.EditorFontSize;
        setFont(getFont().deriveFont(font_size));
        //-------------------------
        setText(Utils.ReadAllText(file.file).replace("\r", " "));
        gotoLine(file.lastLine);
        //-------------------------
        addCaretListener(сe -> UpdateCaretInfo());
        getDocument().addDocumentListener(new DocumentListener() {
            @Override
            public void removeUpdate(DocumentEvent e) {
            }
            @Override
            public void insertUpdate(DocumentEvent e) {
            }
            @Override
            public void changedUpdate(DocumentEvent arg0) {
                if (!switching_language) {
                    file.NeedsSave = true;
                    if (enable_text_changed && file.state != FileState.Excluded) {
                        Global.mainModule.getSapfor().ResetAllAnalyses();
                        //текст изменился, значит M ка более не актуальна.
                        file.father.dropLastModification();
                    }
                    Global.mainModule.getPass(PassCode.Save).Reset();
                }
            }
        });
        //----
        addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.isControlDown()) {
                    switch (e.getKeyCode()) {
                        case KeyEvent.VK_F:
                            Global.mainModule.getUI().ShowSearchForm(false);
                            break;
                        case KeyEvent.VK_H:
                            Global.mainModule.getUI().ShowSearchForm(true);
                            break;
                    }
                }
            }
        });
    }
    //---------------------------------------------------->>
    public static String getLastWord(String text, char... separators) {
        Vector<Character> separators_ = new Vector<>();
        for (char s : separators)
            separators_.add(s);
        String res = "";
        char[] letters = text.toCharArray();
        for (int i = letters.length - 1; i >= 0; --i) {
            char c = letters[i];
            if (separators_.contains(c)) break;
            else res = c + res;
        }
        return res;
    }
    public static String getFirstWord(String text, char... separators) {
        Vector<Character> separators_ = new Vector<>();
        for (char s : separators)
            separators_.add(s);
        String res = "";
        char[] letters = text.toCharArray();
        for (int i = 0; i < letters.length; ++i) {
            char c = letters[i];
            if (separators_.contains(c)) break;
            else res += c;
        }
        return res;
    }
    public CaretInfo getCaretInfo() {
        return caretInfo;
    }
    public void UpdateCaretInfo() {
        caretInfo = new CaretInfo(this);
        autoComplete.Parse();
    }
    @Override
    public void ClearHighlights() {
        highlighter.removeAllHighlights();
    }
    @Override
    public void ClearLoopsHighLights() {
        for (Object loop : loopsHighlights)
            highlighter.removeHighlight(loop);
    }
    @Override
    public void ClearGOCVHighlights() {
        for (Object line : gcovHighlights)
            highlighter.removeHighlight(line);
    }
    @Override
    public void HighlightLoops() {
        ClearLoopsHighLights();
        for (Loop loop : file.AllLoops.values()) {
            Highlighter.HighlightPainter painter = loop.getLoopState().getPainter();
            if (painter != null) {
                try {
                    loopsHighlights.add(highlighter.addHighlight(
                            getLineStartOffset(loop.line - 1),
                            getLineEndOffset(loop.line - 1),
                            painter
                    ));
                } catch (BadLocationException ex) {
                    Utils_.MainLog.PrintException(ex);
                }
            }
        }
    }
    //нумерация с нуля!
    boolean lineNumberIsValid(int num) {
        return (num >= 0) && (num < this.getLineCount());
    }
    @Override
    public void HighlightGCOV() {
        ClearGOCVHighlights();
        for (int lineNum : file.gcov_info.line_info.keySet()) {
            Pair<Long, Integer> p = file.gcov_info.line_info.get(lineNum);
            Color color = never;
            if (p.getKey() > 0) {
                color = (p.getValue() >= 0) ?
                        new Color(255, 255, (100 - p.getValue()), 90) : null;
            }
            if (color != null) {
                Highlighter.HighlightPainter painter = new DefaultHighlighter.DefaultHighlightPainter(color);
                try {
                    gcovHighlights.add(highlighter.addHighlight(
                            getLineStartOffset(lineNum),
                            getLineEndOffset(lineNum),
                            painter
                    ));
                } catch (Exception ignored) {
                }
            }
        }
    }
    @Override
    protected void saveFont() {
        Global.mainModule.getPass(PassCode.UpdateProperty).Do(
                "EditorFontSize",
                getFont().getSize());
    }
    @Override
    protected void saveText() {
        Global.mainModule.getPass(PassCode.Save).Do();
    }
    @Override
    protected StyledPopupMenu createMenu() {
        return new MainEditorMenu(this);
    }
    public int getCurrentLine() {
        return getCaretLineNumber() + 1;
    }
    public int getCurrentSymbol() {
        return getCaretOffsetFromLineStart() + 1;
    }
}
