/* FichothequeLib_Tools - Copyright (c) 2023-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 CssPropertyResolver extends AbstractStepResolver {

    private final static short ERROR_STEP = 0;
    private final static short NAME_STEP = 1;
    private final static short VALUE_STEP = 2;
    private final static short VALUE_NUMBER_STEP = 3;
    private final static short ONQUOTE_STEP = 5;
    private final static short WAITING_NAME_STEP = 11;
    private final static short WAITING_OPERATOR_STEP = 12;
    private final static short WAITING_VALUE_STEP = 13;
    private int step;
    private char currentQuote;

    private CssPropertyResolver() {
        step = WAITING_NAME_STEP;
    }

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

    @Override
    public String getStepClassName(String textPart, boolean lastPart) {
        switch (step) {
            case NAME_STEP:
                return "cm-property";
            case VALUE_STEP:
                return "cm-atom";
            case VALUE_NUMBER_STEP:
                return "cm-number";
            case ERROR_STEP:
                return "cm-error";
            case ONQUOTE_STEP:
                return "cm-string";
            default:
                return null;
        }
    }

    private void resolveSpace() {
        boolean appendToCurrent = false;
        switch (step) {
            case ONQUOTE_STEP:
            case ERROR_STEP:
                appendToCurrent = true;
                break;
            case VALUE_STEP:
            case VALUE_NUMBER_STEP:
                flush();
                step = WAITING_VALUE_STEP;
                break;
            case NAME_STEP:
                flush();
                step = WAITING_OPERATOR_STEP;
                break;
        }
        if (appendToCurrent) {
            appendToCurrent(' ');
        } else {
            appendSpaceToFinal();
        }
    }

    private void resolveDelimiter() {
        switch (step) {
            case ONQUOTE_STEP:
                appendToCurrent(';');
                break;
            default:
                flush();
                appendToFinal("cm-punctuation", ";");
                step = WAITING_NAME_STEP;
        }
    }

    private void resolveOperator() {
        switch (step) {
            case ONQUOTE_STEP:
            case ERROR_STEP:
                appendToCurrent(':');
                break;
            case NAME_STEP:
            case WAITING_OPERATOR_STEP:
                flush();
                appendOperator(":");
                step = WAITING_VALUE_STEP;
                break;
            default:
                flush();
                appendToCurrent(':');
                step = ERROR_STEP;
                break;
        }
    }

    private void appendChar(char carac) {
        boolean appendToCurrent = true;
        switch (step) {
            case WAITING_NAME_STEP: {
                step = NAME_STEP;
                break;
            }
            case WAITING_OPERATOR_STEP: {
                flush();
                step = ERROR_STEP;
                break;
            }
            case WAITING_VALUE_STEP: {
                flush();
                switch (carac) {
                    case '\'':
                    case '"':
                        currentQuote = carac;
                        step = ONQUOTE_STEP;
                        break;
                    default:
                        if (Character.isDigit(carac)) {
                            step = VALUE_NUMBER_STEP;
                        } else {
                            step = VALUE_STEP;
                        }
                }
                break;
            }
            case ONQUOTE_STEP: {
                if (carac == currentQuote) {
                    appendToCurrent(carac);
                    flush();
                    step = WAITING_VALUE_STEP;
                    appendToCurrent = false;
                }
                break;
            }

        }
        if (appendToCurrent) {
            appendToCurrent(carac);
        }
    }


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

}
