import { LanguageSupport, StreamLanguage } from "@codemirror/language";
import { tags as t } from "@lezer/highlight";

export const zoekt = () => {
    const zoektLanguage = StreamLanguage.define({
        startState() {
            return {
                inString: false,
                escaped: false
            };
        },
        token(stream, state) {
            // Handle strings
            if (state.inString) {
                if (state.escaped) {
                    state.escaped = false;
                    stream.next();
                    return t.string.toString();
                }
                const ch = stream.next();
                if (ch === "\\") {
                    state.escaped = true;
                    return t.string.toString();
                } else if (ch === '"') {
                    // End of string
                    state.inString = false;
                    return t.string.toString();
                } else {
                    return t.string.toString();
                }
            }

            // Skip whitespace
            if (stream.eatSpace()) {
                return null;
            }

            // Negation operator
            if (stream.match(/-/)) {
                return t.operator.toString();
            }

            // Parentheses
            if (stream.match("(") || stream.match(")")) {
                return t.paren.toString();
            }

            // Check for prefixes first
            // If these match, we return 'keyword'
            if (stream.match(/(archived:|rev:|content:|f:|file:|fork:|visibility:|r:|repo:|regex:|lang:|sym:|t:|type:|context:)/)) {
                return t.keyword.toString();
            }

            // Now try matching a standalone word
            // If the word is "or", return keyword; else nothing special
            if (stream.match(/[A-Za-z0-9_]+/)) {
                const word = stream.current();
                if (word === "or") {
                    return t.keyword.toString();
                }
                return null;
            }

            // Double-quoted string start
            if (stream.peek() === '"') {
                stream.next(); // consume opening quote
                state.inString = true;
                return t.string.toString();
            }

            // If we reach here, consume a single character and return null
            stream.next();
            return null;
        }
    });

    return new LanguageSupport(zoektLanguage);
};
