/* FichothequeLib_Tools - Copyright (c) 2025 Vincent Calame - Exemole
 * Logiciel libre donné sous triple licence :
 * 1) selon les termes de la CeCILL V2
 * 2) selon les termes de l’EUPL V.1.1
 * 3) selon les termes de la GNU GPLv3
 * Voir le fichier licences.txt
 */


package net.fichotheque.tools.extraction.syntaxes;


/**
 *
 * @author Vincent Calame
 */
public class ChainResolver extends AbstractStepResolver {

    private final static short TOKEN_STEP = 1;
    private final static short ARGUMENTS_STEP = 2;
    private final static short ONQUOTE_STEP = 3;
    private final static short TOKEN_METHOD_STEP = 4;
    private final static short ROOT_TOKEN_STEP = 5;
    private int step;
    private char currentQuote;

    private ChainResolver() {
        step = ROOT_TOKEN_STEP;
    }

    @Override
    public void resolveChar(char carac) {
        switch (carac) {
            case ' ':
                resolveSpace();
                break;
            case '.':
                resolveSeparator();
                break;
            default:
                appendChar(carac);
        }
    }

    @Override
    public String getStepClassName(String textPart, boolean end) {
        switch (step) {
            case ROOT_TOKEN_STEP: {
                switch (textPart) {
                    case "this":
                    case "self":
                        return "cm-chain-keyword";
                    default:
                        return "cm-chain-root";
                }
            }
            case TOKEN_STEP:
                return getTokenClassName(textPart, end);
            case ARGUMENTS_STEP:
                return "cm-chain-argument";
            case ONQUOTE_STEP:
                return "cm-string";
            case TOKEN_METHOD_STEP:
                return "cm-chain-method";
            default:
                return null;
        }
    }

    private void resolveSpace() {
        boolean appendToCurrent = false;
        switch (step) {
            case ONQUOTE_STEP:
            case ARGUMENTS_STEP:
                appendToCurrent = true;
                break;
            default:
                flush();
                step = TOKEN_STEP;
        }
        if (appendToCurrent) {
            appendToCurrent(' ');
        } else {
            appendSpaceToFinal();
        }
    }

    private void resolveSeparator() {
        boolean appendToCurrent = false;
        switch (step) {
            case ONQUOTE_STEP:
                appendToCurrent = true;
                break;
            default:
                flush();
                step = TOKEN_STEP;
        }
        if (appendToCurrent) {
            appendToCurrent('.');
        } else {
            appendPunctuation(".");
        }
    }

    private void appendChar(char carac) {
        boolean appendToCurrent = true;
        switch (step) {
            case ROOT_TOKEN_STEP:
            case TOKEN_STEP: {
                switch (carac) {
                    case '(':
                        step = TOKEN_METHOD_STEP;
                        flush();
                        appendBracket("(");
                        appendToCurrent = false;
                        step = ARGUMENTS_STEP;
                        break;
                }
                break;
            }
            case ARGUMENTS_STEP: {
                switch (carac) {
                    case '\'':
                    case '"':
                        currentQuote = carac;
                        step = ONQUOTE_STEP;
                        break;
                    case ')':
                        flush();
                        appendBracket(")");
                        appendToCurrent = false;
                        step = TOKEN_STEP;
                        break;
                }
                break;
            }
            case ONQUOTE_STEP: {
                if (carac == currentQuote) {
                    appendToCurrent(carac);
                    flush();
                    step = ARGUMENTS_STEP;
                    appendToCurrent = false;
                }
                break;
            }
        }
        if (appendToCurrent) {
            appendToCurrent(carac);
        }
    }


    private String getTokenClassName(String textPart, boolean lastPart) {
        if (Character.isUpperCase(textPart.charAt(0))) {
            if (lastPart) {
                return "cm-chain-constant";
            } else {
                return "cm-chain-class";
            }
        } else {
            return "cm-chain-property";
        }
    }

    public static String resolve(String value) {
        if (value.isEmpty()) {
            return "";
        }
        ChainResolver resolver = new ChainResolver();
        resolver.resolveText(value);
        return resolver.end();
    }

}
