package _VisualDVM.Validators;
import Common.Utils.Utils_;
import _VisualDVM.GlobalData.Compiler.Compiler;
import _VisualDVM.GlobalData.CompilerEnvironment.CompilerEnvironment;
import _VisualDVM.GlobalData.CompilerOption.CompilerOption;

import java.util.Arrays;
public class DVMHelpParser {
    public static HelpParserState state;
    public static String t_line;
    public static String line;
    //-
    public static OptionState optionState;
    public static CompilerOption option;
    //-
    public static int spacesCounter;
    public static CompilerEnvironment environment;
    public static EnvironmentState environmentState;
    //-
    public static String descriptionLine = "";
    //-
    public static Compiler compiler = null;
    public static String[] banned_options = new String[]{
            "-o",
            "-c",
            "-f90",
            "-FI"
    };
    public static void ResetOption() {
        optionState = OptionState.SearchName;
        option = null;
        descriptionLine = "";
    }
    public static void TryConfirmOptionDescriptionLine() {
        if (option != null && !descriptionLine.isEmpty()) {
            option.description.add(descriptionLine.trim());
            descriptionLine = "";
        }
    }
    public static void TryConfirmOption() {
        if ((option != null) && (!compiler.options.containsKey(option.name))) {
            if (!descriptionLine.isEmpty())
                option.description.add(descriptionLine.trim());
            option.CheckParameterVariants();
            if (!Arrays.asList(banned_options).contains(option.name)) {
                compiler.options.put(option.name, option);
            }
            ResetOption();
        }
    }
    public static void ResetEnvironment() {
        environmentState = EnvironmentState.SearchName;
        spacesCounter = 0;
        environment = null;
        descriptionLine = "";
    }
    public static void TryConfirmEnvironmentDescriptionLine() {
        if (environment != null && !descriptionLine.isEmpty()) {
            environment.description.add(descriptionLine.trim());
            descriptionLine = "";
        }
    }
    public static void TryConfirmEnvironment() {
        if ((environment != null) && (!compiler.environments.containsKey(environment.name))) {
            if (!descriptionLine.isEmpty())
                environment.description.add(descriptionLine.trim());
            environment.CheckDefaults();
            compiler.environments.put(environment.name, environment);
            ResetEnvironment();
        }
    }
    public static void ReadOptions(Compiler compiler_in) {
        compiler = compiler_in;
        String[] lines = compiler.helpText.split("\n");
        state = HelpParserState.Search;
        for (String line_ : lines) {
            line = line_; //нужна для окружения. там пробелы нужно считать сразу.
            t_line = Utils_.removeCharacters(line_.trim(), "\r");
            switch (state) {
                case Search:
                    switch (t_line) {
                        case "Output and debugging options:":
                        case "Convertation options:":
                        case "Optimization options:":
                            state = HelpParserState.OptionsChapter;
                            ResetOption();
                            break;
                        case "Environment variables":
                            state = HelpParserState.EnvironmentsChapterHeader;
                            break;
                    }
                    break;
                case EnvironmentsChapterHeader:
                    state = HelpParserState.EnvironmentsChapter;
                    ResetEnvironment();
                    break;
                case OptionsChapter:
                    if (t_line.isEmpty()) {
                        TryConfirmOption();
                        state = HelpParserState.Search;
                    } else {
                        char[] symbols = t_line.toCharArray();
                        //- Новая строка.
                        optionState = OptionState.SearchName;
                        //-
                        for (char c : symbols) {
                            switch (optionState) {
                                case SearchName:
                                    switch (c) {
                                        case '-':
                                            TryConfirmOption();
                                            //-
                                            option = new CompilerOption();
                                            option.name += c;
                                            optionState = OptionState.Name;
                                            break;
                                        default:
                                            descriptionLine += c;
                                            optionState = OptionState.Description;
                                            break;
                                    }
                                    break;
                                case Name:
                                    switch (c) {
                                        case '<':
                                            optionState = OptionState.Parameter;
                                            break;
                                        case ' ':
                                        case '=':
                                        case '\t':
                                            option.parameterSeparator += c;
                                            optionState = OptionState.SearchParameter;
                                            break;
                                        default:
                                            option.name += c;
                                            break;
                                    }
                                    break;
                                case SearchParameter:
                                    if (c == '<') {
                                        optionState = OptionState.Parameter;
                                    } else {
                                        option.parameterSeparator = "";
                                        optionState = OptionState.Description;
                                        descriptionLine += c;
                                    }
                                    break;
                                case Parameter:
                                    if (c == '>') {
                                        optionState = OptionState.SearchDescription;
                                    } else {
                                        option.parameterName += c;
                                    }
                                    break;
                                case SearchDescription:
                                    if (c != ' ') {
                                        descriptionLine += c;
                                        optionState = OptionState.Description;
                                    }
                                    break;
                                case Description:
                                    descriptionLine += c;
                                    break;
                            }
                        }
                        //-
                        TryConfirmOptionDescriptionLine();
                    }
                    break;
                case EnvironmentsChapter:
                    if (t_line.isEmpty()) {
                        TryConfirmEnvironment();
                        state = HelpParserState.Search;
                    } else {
                        char[] symbols = line.toCharArray();
                        //- Новая строка.
                        environmentState = EnvironmentState.SearchName;
                        spacesCounter = 0;
                        //-
                        for (char c : symbols) {
                            switch (environmentState) {
                                case SearchName:
                                    if (c == ' ') {
                                        if (spacesCounter++ > 4) {
                                            //имя нам уже не встретится. это строка описания.
                                            environmentState = EnvironmentState.Description;
                                        }
                                    } else if (Character.isLetter(c)) {
                                        if (spacesCounter == 4) {
                                            TryConfirmEnvironment();
                                            environment = new CompilerEnvironment();
                                            environment.name += c;
                                            environmentState = EnvironmentState.Name;
                                        }
                                    } else {
                                        descriptionLine += c;
                                        environmentState = EnvironmentState.Description;
                                    }
                                    break;
                                case Name:
                                    //в имени окружения пробелов быть не может. ждем описания.
                                    if (c == ' ') {
                                        environmentState = EnvironmentState.SearchDescription;
                                    } else if (Character.isLetterOrDigit(c) || c == '_') {
                                        //буквы цифры и подчеркивания - имя продолжается.
                                        environment.name += c;
                                    } else {
                                        descriptionLine += c;
                                        environmentState = EnvironmentState.Description;
                                    }
                                    break;
                                case SearchDescription:
                                    if (c == ' ') {
                                        //игнорируем.
                                    } else {
                                        descriptionLine += c;
                                        environmentState = EnvironmentState.Description;
                                    }
                                    break;
                                case Description:
                                    descriptionLine += c;
                                    break;
                            }
                            TryConfirmOptionDescriptionLine();
                        }
                        //-
                        TryConfirmEnvironmentDescriptionLine();
                    }
                    break;
            }
        }
    }
    //------------------------------------------------------------------------------------>>
}
