/* FichothequeLib_Tools - Copyright (c) 2007-2024 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.parsers.span;

import java.text.ParseException;
import net.fichotheque.corpus.fiche.Atts;
import net.fichotheque.corpus.fiche.S;
import net.fichotheque.tools.parsers.AttsParser;
import net.fichotheque.tools.parsers.TypoParser;
import static net.fichotheque.tools.parsers.span.SpanParser.getStopIndex;
import static net.fichotheque.tools.parsers.span.SpanParser.getValue;
import net.mapeadores.util.text.TypoOptions;


/**
 *
 * @author Vincent Calame
 */
class BracketsParser extends SpanParser {

    private final TypoOptions typoOptions;

    BracketsParser(TypoOptions typoOptions) {
        this.typoOptions = typoOptions;
    }

    @Override
    public char getStartChar() {
        return '[';
    }

    @Override
    public SpanParseResult parse(String source, int startIndex) {
        if (startIndex > (source.length() - 3)) {
            return SpanParseResult.IGNORE_RESULT_1;
        }
        char initialCarac = source.charAt(startIndex + 1);
        char nextChar = source.charAt(startIndex + 2);
        if (initialCarac == '%') {
            if (nextChar == ']') {//Cas particulier [%]
                return new SpanParseResult(new S(S.BR), startIndex + 2);
            }
        }
        if ((nextChar != '(') && (nextChar != ' ')) {
            return SpanParseResult.IGNORE_RESULT_1;
        }
        short spanType;
        try {
            spanType = S.initialToType(initialCarac);
        } catch (IllegalArgumentException iae) {
            return SpanParseResult.SYNTAX_EROR_RESULT_1;
        }
        if (nextChar == ' ') {
            return parseValueOnlySpan(source, spanType, startIndex + 3, typoOptions);
        } else {
            return parseStandardSpan(source, spanType, startIndex + 3, typoOptions);
        }
    }

    private static SpanParseResult parseValueOnlySpan(String source, short spanType, int beginIndex, TypoOptions typoOptions) {
        int stopIndex = getStopIndex(source, beginIndex, ']');
        if (stopIndex == - 1) {
            return SpanParseResult.SYNTAX_EROR_RESULT_1;
        }
        String value = getValue(source, beginIndex, stopIndex, ']');
        if (S.isTypoType(spanType)) {
            value = TypoParser.parseTypo(value, typoOptions);
        }
        if (S.isRefDefaultValue(spanType)) {
            switch (value) {
                case "-":
                    value = "";
                    break;
            }
        }
        S s = new S(spanType);
        s.setValue(value);
        return new SpanParseResult(s, stopIndex);
    }

    private static SpanParseResult parseStandardSpan(String source, short spanType, int beginIndex, TypoOptions typoOptions) {
        RefTest refTest;
        try {
            refTest = RefTest.parse(source, beginIndex);
        } catch (ParseException pe) {
            return SpanParseResult.SYNTAX_EROR_RESULT_1;
        }
        String ref = refTest.getRef();
        int closeIndex = refTest.getCloseIndex();
        Atts atts = null;
        if (refTest.hasAtts()) {
            try {
                AttsParser attsParser = new AttsParser(source, closeIndex + 1);
                attsParser.run();
                closeIndex = attsParser.getCloseIndex();
                atts = attsParser.getAtts();
            } catch (ParseException pe) {
                return SpanParseResult.SYNTAX_EROR_RESULT_1;
            }
        }
        int stopIndex = getStopIndex(source, closeIndex + 1, ']');
        if (stopIndex == - 1) {
            return SpanParseResult.SYNTAX_EROR_RESULT_1;
        }
        String value = getValue(source, closeIndex + 1, stopIndex, ']');
        if (S.isTypoType(spanType)) {
            value = TypoParser.parseTypo(value, typoOptions);
        }
        if (S.isRefDefaultValue(spanType)) {
            switch (value) {
                case "":
                    value = ref;
                    break;
                case "-":
                    value = "";
                    break;
            }
        }
        S s = new S(spanType);
        s.setRef(ref);
        if (atts != null) {
            int attLength = atts.size();
            for (int i = 0; i < attLength; i++) {
                s.putAtt(atts.getName(i), atts.getValue(i));
            }
        }
        s.setValue(value);
        return new SpanParseResult(s, stopIndex);
    }

}
