/* UtilLib - Copyright (c) 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.mapeadores.util.text.search;

import java.util.ArrayList;
import java.util.List;
import net.mapeadores.util.text.TextConstants;
import net.mapeadores.util.text.lexie.LexieParseHandler;
import net.mapeadores.util.text.lexie.LexieParser;


/**
 *
 * @author Vincent Calame
 */
public class SearchTokenParser {

    private final String source;
    private final int defaultSearchType;
    private final List<SearchToken> tokenList = new ArrayList<SearchToken>();
    private final List<SimpleSearchToken> quoteList = new ArrayList<SimpleSearchToken>();
    private int currentType = TextConstants.MATCHES;
    private String currentWord = null;
    private boolean onQuote = false;

    private SearchTokenParser(String source, int defaultSearchType) {
        this.source = source;
        this.defaultSearchType = defaultSearchType;
    }

    private List<SearchToken> parse() {
        LexieParser.parse(source, new InternalHandler());
        if (onQuote) {
            flushQuote();
        } else {
            flushCurrentWord();
        }
        return tokenList;
    }

    private void flushCurrentWord() {
        if (currentWord != null) {
            if (onQuote) {
                quoteList.add(SearchUtils.toSimpleSearchToken(currentWord, currentType));
            } else {
                tokenList.add(SearchUtils.toSimpleSearchToken(currentWord, currentType | defaultSearchType));
            }
            currentWord = null;
            currentType = TextConstants.MATCHES;
        }
    }

    private void flushQuote() {
        flushCurrentWord();
        int size = quoteList.size();
        if (size > 0) {
            SimpleSearchToken[] array = new SimpleSearchToken[size];
            for (int j = 0; j < size; j++) {
                array[j] = quoteList.get(j);
            }
            int p = tokenList.size();
            tokenList.add(SearchUtils.toMultiSearchToken(array));
        }
        onQuote = false;
        quoteList.clear();
    }

    public static List<SearchToken> parse(String source, int defaultSearchType) {
        SearchTokenParser parser = new SearchTokenParser(source, defaultSearchType);
        return parser.parse();
    }


    private class InternalHandler implements LexieParseHandler {

        private InternalHandler() {

        }

        @Override
        public void flushLexie(String word, int wordStart) {
            flushCurrentWord();
            currentWord = word;
        }

        @Override
        public void checkSpecialChar(char carac) {
            switch (carac) {
                case '*':
                    if (currentWord == null) {
                        currentType = TextConstants.ENDSWITH;
                    } else {
                        currentType = currentType | TextConstants.STARTSWITH;
                        flushCurrentWord();
                    }
                    break;
                case '\"':
                    if (onQuote) {
                        flushQuote();
                    } else {
                        flushCurrentWord();
                        onQuote = true;
                    }
                    break;
                default:
                    flushCurrentWord();
            }
        }

    }

}
