/*
 * SDK Pullenti Lingvo, version 4.33, fabruary 2026. Copyright (c) 2013-2026, Pullenti. All rights reserved. 
 * Non-Commercial Freeware and Commercial Software.
 * This class is generated using the converter Unisharping (www.unisharping.ru) from Pullenti C# project. 
 * The latest version of the code is available on the site www.pullenti.ru
 */

package com.pullenti.ner.core;

/**
 * Элемент составного номера
 */
public class SingleNumToken extends com.pullenti.ner.MetaToken {

    public SingleNumToken(com.pullenti.ner.Token b, com.pullenti.ner.Token e) {
        super(b, e, null);
    }

    /**
     * Значение номера (несколько вариантов - в случае неоднозначности)
     */
    public java.util.ArrayList<SingleNumValue> vals = new java.util.ArrayList<SingleNumValue>();

    /**
     * Исходное строковое значение
     */
    public String value;

    /**
     * Возмодный префикс
     */
    public String prefix;

    /**
     * Возможный суффикс
     */
    public String suffix;

    @Override
    public String toString() {
        StringBuilder res = new StringBuilder();
        res.append(value).append(": ");
        for (int i = 0; i < vals.size(); i++) {
            if (i > 0) 
                res.append("/");
            res.append(vals.get(i).toString());
        }
        return res.toString();
    }

    public String getNormal() {
        if (vals.size() == 0) 
            return "?";
        if (vals.get(0).typ == SingleNumValueType.LETTER) 
            return (String.valueOf(vals.get(0).letter));
        return ((Integer)vals.get(0).val).toString();
    }


    private void _addNum(int val, boolean rom, boolean upper) {
        SingleNumValue res = new SingleNumValue();
        res.val = val;
        if (rom) 
            res.typ = SingleNumValueType.ROMAN;
        if (rom && upper) 
            vals.add(0, res);
        else 
            vals.add(res);
    }

    private void _addChar(char ch, boolean up) {
        for (SingleNumValue v : vals) {
            if (ch == v.letter) 
                return;
        }
        SingleNumValue res = new SingleNumValue();
        res.typ = SingleNumValueType.LETTER;
        res.letter = Character.toLowerCase(ch);
        res.upper = up;
        vals.add(res);
    }

    public static SingleNumToken tryParse(com.pullenti.ner.Token t, boolean first, boolean force) {
        if (t == null) 
            return null;
        if (t.isValue("I", null)) {
        }
        if (!first && t.isWhitespaceBefore()) {
            if (!force && !t.isCharOf(".(<")) 
                return null;
        }
        com.pullenti.ner.Token t0 = t;
        SingleNumToken res = null;
        if (t.isChar('(') && !t.isWhitespaceAfter()) {
            res = tryParse(t.getNext(), first, false);
            if (res != null && res.getEndToken().isChar(')')) {
                res.setBeginToken(t);
                res.prefix = "(";
                return res;
            }
            else 
                return null;
        }
        if (t.isChar('<') && !t.isWhitespaceAfter()) {
            res = tryParse(t.getNext(), first, false);
            if (res != null && res.getEndToken().isChar('>')) {
                res.setBeginToken(t);
                res.prefix = "<";
                if (!first) {
                    res.prefix = (res.suffix = null);
                    res.value = "<" + res.value;
                }
                if (!res.getEndToken().isWhitespaceAfter()) {
                    t = res.getEndToken().getNext();
                    if (t != null) {
                        if (t.isCharOf(".])\\")) {
                            res.setEndToken(t);
                            res.suffix = t.getSourceText();
                            res.value += res.suffix;
                        }
                    }
                }
            }
            return res;
        }
        boolean hasPref = false;
        if (first) {
            com.pullenti.ner.Token tt = MiscHelper.checkNumberPrefix(t);
            if (tt != null && !tt.isCharOf(".)")) {
                if (t.isNewlineBefore()) {
                    hasPref = true;
                    t = tt;
                }
                else if (t.getPrevious() != null && ((_checkKeyword(t.getPrevious()) || t.getPrevious().isNewlineBefore()))) {
                    hasPref = true;
                    t = tt;
                }
            }
        }
        com.pullenti.ner.NumberToken nt = (com.pullenti.ner.NumberToken)com.pullenti.unisharp.Utils.cast(t, com.pullenti.ner.NumberToken.class);
        if (nt != null && nt.getIntValue() != null && (nt.getIntValue() < 3000)) {
            if (nt.typ == com.pullenti.ner.NumberSpellingType.WORDS && t == t0) {
                if (!first) 
                    return null;
                if (force) {
                }
                else if (!t.isNewlineBefore() && _checkKeyword(t.getPrevious())) {
                }
                else if (t.getNext() != null && !t.isNewlineAfter() && _checkKeyword(t.getNext())) {
                }
                else 
                    return null;
            }
            if (t.getNext() != null) {
                if (t.getNext().isValue("ГОД", null) || t.getNext().isValue("ЛЕТ", null)) 
                    return null;
            }
            res = new SingleNumToken(t0, t);
            res._addNum(((com.pullenti.ner.NumberToken)com.pullenti.unisharp.Utils.cast(t, com.pullenti.ner.NumberToken.class)).getIntValue(), false, false);
        }
        else if ((t instanceof com.pullenti.ner.TextToken) && t.chars.isLetter() && t.getLengthChar() == 1) {
            if (com.pullenti.unisharp.Utils.isNullOrEmpty(((com.pullenti.ner.TextToken)com.pullenti.unisharp.Utils.cast(t, com.pullenti.ner.TextToken.class)).term)) 
                return null;
            if (t.getNext() != null && t.getNext().isCharOf(")")) {
            }
            else if (!first || force) {
            }
            else {
                if (t.getPrevious() != null && t.getPrevious().isCharOf("(<") && ((t.getPrevious().isNewlineBefore() || _checkKeyword(t.getPrevious().getPrevious())))) {
                }
                else if (_checkKeyword(t.getPrevious())) {
                }
                else if (t.chars.isAllUpper() && t.isCharOf("IXХ") && !t.isWhitespaceAfter()) {
                }
                else if (t.isNewlineBefore() && !t.isWhitespaceAfter()) {
                }
                else 
                    return null;
                if (t.getNext() != null && t.getNext().isCharOf(".)>")) {
                }
                else if (!t.isWhitespaceAfter() && t.getNext().isChar('(')) {
                }
                else if (t.isNewlineAfter()) {
                }
                else 
                    return null;
            }
            nt = null;
            if (t.chars.isAllUpper() || t.isValue("I", null)) 
                nt = NumberHelper.tryParseRoman(t);
            boolean up = t.chars.isAllUpper();
            res = new SingleNumToken(t0, t);
            char ch = ((com.pullenti.ner.TextToken)com.pullenti.unisharp.Utils.cast(t, com.pullenti.ner.TextToken.class)).term.charAt(0);
            res._addChar(ch, up);
            if (((int)ch) < 0x80) {
                char cyr = com.pullenti.morph.LanguageHelper.getCyrForLat(ch);
                if (cyr != ((char)0)) 
                    res._addChar(cyr, up);
            }
            else {
                char lat = com.pullenti.morph.LanguageHelper.getLatForCyr(ch);
                if (lat != ((char)0)) 
                    res._addChar(lat, up);
            }
            if (ch == 'I') 
                res._addNum(1, true, up);
            if (ch == 'V') 
                res._addNum(5, true, up);
            if (ch == 'X' || ch == 'Х') 
                res._addNum(10, true, up);
        }
        else if (t.isCharOf("ˡ¹²³")) {
            res = new SingleNumToken(t, t);
            res._addNum((t.isCharOf("ˡ¹") ? 1 : (t.isChar('²') ? 2 : 3)), false, false);
        }
        else {
            nt = NumberHelper.tryParseRoman(t);
            if (nt == null || nt.getIntValue() == null) 
                return null;
            boolean ok = false;
            if (!first || force) 
                ok = true;
            else if (t.getNext() != null && t.getNext().isCharOf(".)")) 
                ok = true;
            else if (!t.isNewlineBefore() && _checkKeyword(t.getPrevious())) 
                ok = true;
            if (!ok) 
                return null;
            res = new SingleNumToken(t0, t);
            res._addNum(nt.getIntValue(), true, nt.chars.isAllUpper());
        }
        if (res == null) 
            return null;
        if (!res.getEndToken().isWhitespaceAfter()) {
            t = res.getEndToken().getNext();
            if (t != null) {
                if (t.isCharOf(".])>\\")) {
                    res.setEndToken(t);
                    res.suffix = t.getSourceText();
                }
            }
        }
        if (res.value == null) 
            res.value = res.getSourceText();
        if ((!hasPref && first && !force) && res.suffix == null && !res.isNewlineAfter()) {
            com.pullenti.ner.Token tt = res.getEndToken().getNext();
            if ((tt instanceof com.pullenti.ner.TextToken) && tt.chars.isAllLower()) 
                return null;
        }
        if (res.value.length() == 1 && res.suffix == null && res.prefix == null) {
            if (Character.isLetter(res.value.charAt(0)) && res.getBeginToken().chars.isAllUpper()) {
                if (res.getBeginToken().getNext() != null && res.getBeginToken().getNext().chars.isAllLower()) 
                    return null;
            }
        }
        return res;
    }

    private static boolean _checkKeyword(com.pullenti.ner.Token t) {
        if (!(t instanceof com.pullenti.ner.TextToken)) 
            return false;
        String term = ((com.pullenti.ner.TextToken)com.pullenti.unisharp.Utils.cast(t, com.pullenti.ner.TextToken.class)).term;
        if (((com.pullenti.unisharp.Utils.stringsEq(term, "СТАТЬЯ") || com.pullenti.unisharp.Utils.stringsEq(term, "ГЛАВА") || com.pullenti.unisharp.Utils.stringsEq(term, "РАЗДЕЛ")) || com.pullenti.unisharp.Utils.stringsEq(term, "ЧАСТЬ") || com.pullenti.unisharp.Utils.stringsEq(term, "ПОДРАЗДЕЛ")) || com.pullenti.unisharp.Utils.stringsEq(term, "ПАРАГРАФ") || com.pullenti.unisharp.Utils.stringsEq(term, "ПОДПАРАГРАФ")) 
            return true;
        return false;
    }

    public boolean isOne() {
        for (SingleNumValue v : vals) {
            if (v.isOne()) 
                return true;
        }
        return false;
    }


    public void correct(SingleNumToken prev) {
        if (prev == null) {
            if (isOne()) {
                for (int i = vals.size() - 1; i >= 0; i--) {
                    if (!vals.get(i).isOne()) 
                        vals.remove(i);
                }
            }
            return;
        }
        SingleNumComparer comp = new SingleNumComparer();
        comp.process(prev, this);
        if (comp.typ != ComplexNumCompareType.LESS) 
            return;
        for (int i = prev.vals.size() - 1; i >= 0; i--) {
            if (prev.vals.get(i) != comp.val1) 
                prev.vals.remove(i);
        }
        for (int i = vals.size() - 1; i >= 0; i--) {
            if (vals.get(i) != comp.val2) 
                vals.remove(i);
        }
    }
    public SingleNumToken() {
        super();
    }
}
