/* 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 final class CssResolver extends AbstractStepResolver {

    private final static short TAG_STEP = 1;
    private final static short ID_STEP = 2;
    private final static short CLASS_STEP = 3;
    private final static short CONDITION_STEP = 4;
    private final static short ONQUOTE_STEP = 5;
    private final static short WAITING_TOKEN_STEP = 11;
    private int step;

    private CssResolver() {
        step = WAITING_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 lastPart) {
        switch (step) {
            case TAG_STEP:
                return "cm-tag";
            case ID_STEP:
                return "cm-builtin";
            case CLASS_STEP:
                return "cm-qualifier";
            case CONDITION_STEP:
                return "cm-property";
            default:
                return null;
        }
    }

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

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

    private void appendChar(char carac) {
        boolean appendToCurrent = true;
        switch (step) {
            case WAITING_TOKEN_STEP: {
                switch (carac) {
                    case '#':
                        flush();
                        step = ID_STEP;
                        break;
                    case '.':
                        flush();
                        step = CLASS_STEP;
                        break;
                    default:
                        flush();
                        step = TAG_STEP;
                }
                break;
            }
            case TAG_STEP:
            case ID_STEP:
            case CLASS_STEP: {
                switch (carac) {
                    case '.':
                        flush();
                        step = CLASS_STEP;
                        break;
                    case '[':
                        flush();
                        appendOperator("[");
                        appendToCurrent = false;
                        step = CONDITION_STEP;
                        break;
                }
                break;
            }
            case CONDITION_STEP: {
                switch (carac) {
                    case ']':
                        flush();
                        appendOperator("]");
                        appendToCurrent = false;
                        step = TAG_STEP;
                        break;
                }
                break;
            }
        }
        if (appendToCurrent) {
            appendToCurrent(carac);
        }
    }

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

}
