package _VisualDVM.ProjectData.Files.UI.Editor.AutoComplete.SAPFOR;
import _VisualDVM.ProjectData.Files.UI.Editor.AutoComplete.SAPFOR.Directives.BaseDirective;
import _VisualDVM.ProjectData.Files.UI.Editor.AutoComplete.SAPFOR.Directives.DirectiveName;
import _VisualDVM.ProjectData.Files.UI.Editor.AutoComplete.SAPFOR.Providers.*;
import _VisualDVM.ProjectData.Files.UI.Editor.SPFEditor;
import org.fife.ui.autocomplete.AutoCompletion;
import org.fife.ui.autocomplete.DefaultCompletionProvider;

import java.util.LinkedHashMap;
import java.util.Vector;
public class SapforAutoComplete extends AutoCompletion {
    //---
    public Vector<BaseProvider> providers = new Vector<>();
    public LinkedHashMap<DirectiveName, BaseDirective> directives = new LinkedHashMap<>();
    public Vector<DirectiveName> flags = new Vector<>();
    public DirectiveName nearestGroup;
    private SPFEditor editor = null;
    public SapforAutoComplete(SPFEditor editor_in) {
        //заглушка.
        super(new DefaultCompletionProvider());
        editor = editor_in;
        providers.add(new StartProvider(this));
        providers.add(new TypeProvider(this));
        providers.add(new Spec1Provider(this));
        providers.add(new ReductionProvider(this));
        providers.add(new Spec2Provider(this));
        providers.add(new Spec3Provider(this));
        providers.add(new Spec4Provider(this));
        providers.add(new IntervalProvider(this));
        providers.add(new CheckPointTypeProvider(this));
        install(editor);
        setAutoActivationEnabled(false);
        setAutoCompleteEnabled(false);
        setAutoCompleteSingleChoices(false);
    }
    public SPFEditor getEditor() {
        return editor;
    }
    //---
    public void updateFlags() {
        flags.clear();
        //определить присутствие директив в строке.
        for (DirectiveName name : directives.keySet()) {
            if (name.equals(DirectiveName.SPF)) {
                String line = editor.getCaretInfo().current_line;
                if (line.startsWith("!$")) {
                    boolean ok = true;
                    for (int z = 2; z < line.length(); ++z)
                        if (line.charAt(z) != ' ')
                            ok = false;
                    if (ok)
                        flags.add(DirectiveName.START);
                    else if (editor.getCaretInfo().current_line.contains(name.getText()))
                        flags.add(name);
                }
            } else if (editor.getCaretInfo().current_line.contains(name.getText()))
                flags.add(name);
        }
    }
    public void findNearestGroup() {
        int indicator = 0;
        String word = "";
        SearchState s = SearchState.BracketSearch;
        nearestGroup = DirectiveName.UNDEFINED;
        for (int i = (editor.getCaretInfo().before.length() - 1); i >= 0; i--) {
            char c = editor.getCaretInfo().before.charAt(i);
            switch (s) {
                case BracketSearch:
                    switch (c) {
                        case '(':
                            indicator++;
                            if (indicator > 0)
                                s = SearchState.DirectiveSearch;
                            break;
                        case ')':
                            indicator--;
                            break;
                        default:
                            break;
                    }
                    break;
                case DirectiveSearch:
                    switch (c) {
                        case ' ':
                            break;
                        default:
                            s = SearchState.Directive;
                            word = c + word;
                            break;
                    }
                    break;
                case Directive:
                    word = c + word;
                    for (DirectiveName directiveName : directives.keySet()) {
                        if (directiveName.getText().equals(word)) {
                            nearestGroup = directiveName;
                            return;
                        }
                    }
                    break;
            }
        }
    }
    //вызывается при событиях каретки текстового редактора.
    //обновление меню которое вызовется при Ctrl+Space
    public void Parse() {
        updateFlags();
        findNearestGroup();
        for (BaseDirective directive : directives.values()) {
            //если директива видима, значит ее провайдер нам и нужен.
            if (directive.Check()) {
                if (!directive.getProvider().equals(this.getCompletionProvider()))
                    setCompletionProvider(directive.getProvider());
                doCompletion();
                return;
            }
        }
        //если ничего не нашли, ставим пустого
        //TODO - не такой уж он и пустой!
        setCompletionProvider(providers.get(0));
    }
}

