/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. All rights resvered.
 */
package commonmark4cj.commonmark

/**
 * Attempts to parse an HTML entity or numeric character reference.
 */
public class EntityInlineParser <: InlineContentParser {
    private static let hex: AsciiMatcher = AsciiMatcher
        .builder()
        .range(b'0', b'9')
        .range(b'A', b'F')
        .range(b'a', b'f')
        .build()
    private static let dec: AsciiMatcher = AsciiMatcher.builder().range(b'0', b'9').build()
    private static let entityStart: AsciiMatcher = AsciiMatcher.builder().range(b'A', b'Z').range(b'a', b'z').build()
    private static let entityContinue: AsciiMatcher = entityStart.newBuilder().range(b'0', b'9').build()

    // @Override
    public func tryParse(inlineParserState: InlineParserState): ParsedInline {
        let scanner: Scanner = inlineParserState.getScanner()
        let start: SourcePosition = scanner.position()
        // Skip `&`
        scanner.next()

        let c = scanner.peek()
        if (c == b'#') {
            // Numeric
            scanner.next()
            if (scanner.next(b'x') || scanner.next(b'X')) { /*cjlint-ignore !G.EXP.03 */
                let digits: Int = scanner.matches(hex)
                if (1 <= digits && digits <= 6 && scanner.next(b';')) { /*cjlint-ignore !G.EXP.03 */
                    return entity(scanner, start)
                }
            } else {
                let digits: Int = scanner.matches(dec)
                if (1 <= digits && digits <= 7 && scanner.next(b';')) { /*cjlint-ignore !G.EXP.03 */
                    return entity(scanner, start)
                }
            }
        } else if (entityStart.matches(c)) {
            scanner.matches(entityContinue)
            if (scanner.next(b';')) {
                return entity(scanner, start)
            }
        }

        return ParsedInline.none()
    }

    private func entity(scanner: Scanner, start: SourcePosition): ParsedInline {
        let text: String = scanner.getSource(start, scanner.position()).getContent()
        return ParsedInline.of(Text(Html5Entities.entityToString(text)), scanner.position())
    }
}

public class EntityInlineParserFactory <: InlineContentParserFactory {

    // @Override
    @Frozen
    public func getTriggerCharacters(): HashSet<Rune> {
        return HashSet(r'&')
    }

    // @Override
    @Frozen
    public func create(): InlineContentParser {
        return EntityInlineParser()
    }
}