/*
 * 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.geo.internal;

public class NumToken extends com.pullenti.ner.MetaToken {

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

    public String value;

    public String altValue;

    public boolean hasPrefix;

    public boolean hasSpecWord;

    public boolean isCadasterNumber;

    public String template;

    public String miscType;

    @Override
    public String toString() {
        StringBuilder res = new StringBuilder();
        if (hasPrefix) 
            res.append("№ ");
        res.append(value);
        if (altValue != null) 
            res.append(" / ").append(altValue);
        if (isCadasterNumber) 
            res.append(" cadaster");
        if (miscType != null) 
            res.append(" misc=").append(miscType);
        return res.toString();
    }

    public static NumToken tryParse(com.pullenti.ner.Token t, GeoTokenType typ) {
        if (t == null) 
            return null;
        if (((t.isValue("ОТДЕЛЕНИЕ", null) || t.isValue("КОНТУР", null) || t.isValue("ПОДЪЕМ", null))) && (t.getWhitespacesAfterCount() < 3)) {
            NumToken _next = tryParse(t.getNext(), typ);
            if (_next != null) {
                _next.setBeginToken(t);
                _next.hasPrefix = true;
                _next.hasSpecWord = true;
                _next.miscType = (_next.value + " " + t.getNormalCaseText(com.pullenti.morph.MorphClass.NOUN, com.pullenti.morph.MorphNumber.UNDEFINED, com.pullenti.morph.MorphGender.UNDEFINED, false).toLowerCase());
                return _next;
            }
        }
        if (t.isValue("НАДЕЛ", null) && typ == GeoTokenType.ORG) {
            NumToken _next = tryParse(t.getNext(), typ);
            if (_next != null) {
                _next.setBeginToken(t);
                _next.hasPrefix = true;
                _next.hasSpecWord = true;
                _next.miscType = "надел";
                return _next;
            }
        }
        if (t.isValue2("ЧАСТЬ", "КОНТУРА") && (t.getNext().getWhitespacesAfterCount() < 3)) {
            NumToken _next = tryParse(t.getNext().getNext(), typ);
            if (_next != null) {
                _next.setBeginToken(t);
                _next.hasPrefix = true;
                _next.hasSpecWord = true;
                return _next;
            }
        }
        if (t instanceof com.pullenti.ner.ReferentToken) 
            return null;
        com.pullenti.ner.Token tt = com.pullenti.ner.core.MiscHelper.checkNumberPrefix(t);
        if ((tt == null && (t instanceof com.pullenti.ner.TextToken) && ((com.pullenti.ner.TextToken)com.pullenti.unisharp.Utils.cast(t, com.pullenti.ner.TextToken.class)).term.startsWith("КАД")) && typ != GeoTokenType.STREET) {
            com.pullenti.morph.MorphClass mc = t.getMorphClassInDictionary();
            if (mc.isProperSurname()) 
                return null;
            com.pullenti.ner.Token tt1 = t.getNext();
            if (tt1 != null && tt1.isChar('.')) 
                tt1 = tt1.getNext();
            tt = com.pullenti.ner.core.MiscHelper.checkNumberPrefix(tt1);
            if (tt == null) 
                tt = tt1;
        }
        if (tt != null) {
            boolean hasReest = false;
            for (com.pullenti.ner.Token ttt = tt; ttt != null; ttt = ttt.getNext()) {
                if (((ttt.isCharOf(":") || ttt.isHiphen())) && (ttt.getNext() instanceof com.pullenti.ner.NumberToken)) 
                    continue;
                if (hasReest) {
                    if (ttt.getReferent() instanceof com.pullenti.ner.geo.GeoReferent) 
                        continue;
                }
                TerrItemToken ter = TerrItemToken.tryParse(ttt, null, null);
                if (ter != null && ((ter.ontoItem != null || ter.terminItem != null))) {
                    ttt = ter.getEndToken();
                    continue;
                }
                com.pullenti.ner.core.NounPhraseToken npt = com.pullenti.ner.core.NounPhraseHelper.tryParse(ttt, com.pullenti.ner.core.NounPhraseParseAttr.PARSEPREPOSITION, 0, null);
                if (npt != null) {
                    if (npt.getEndToken().isValue("ЗАПИСЬ", null) || npt.getEndToken().isValue("РЕЕСТР", null)) {
                        ttt = npt.getEndToken();
                        hasReest = true;
                        continue;
                    }
                    break;
                }
                if (!(ttt instanceof com.pullenti.ner.NumberToken)) 
                    break;
                NumToken res = _new1576(t, ttt, true, "n");
                res.value = ((com.pullenti.ner.NumberToken)com.pullenti.unisharp.Utils.cast(ttt, com.pullenti.ner.NumberToken.class)).getValue();
                res._correct(typ);
                return res;
            }
        }
        if (tt == null) 
            tt = t;
        if (tt instanceof com.pullenti.ner.NumberToken) {
            NumToken res = _new1576(t, tt, tt != t, "n");
            res.value = ((com.pullenti.ner.NumberToken)com.pullenti.unisharp.Utils.cast(tt, com.pullenti.ner.NumberToken.class)).getValue();
            res._correct(typ);
            return res;
        }
        if ((tt instanceof com.pullenti.ner.ReferentToken) && (tt.getReferent() instanceof com.pullenti.ner.uri.UriReferent)) {
            NumToken res = _new1578(t, tt, tt != t);
            res.value = tt.getReferent().getStringValue("VALUE");
            String sh = tt.getReferent().getStringValue("SCHEME");
            if (com.pullenti.unisharp.Utils.stringsEq(sh, "КАДАСТР")) 
                res.isCadasterNumber = true;
            return res;
        }
        if (((tt instanceof com.pullenti.ner.TextToken) && !t.isValue("C", null) && !t.isValue("CX", null)) && !t.isValue("СХ", null)) {
            com.pullenti.ner.NumberToken nt = com.pullenti.ner.core.NumberHelper.tryParseRoman(tt);
            if (nt != null && com.pullenti.unisharp.Utils.stringsNe(nt.getValue(), "100")) {
                NumToken res = _new1576(t, nt.getEndToken(), tt != t, "l");
                res.value = nt.getValue();
                res._correct(typ);
                return res;
            }
        }
        if (com.pullenti.ner.core.BracketHelper.isBracket(t, true)) {
            NumToken _next = tryParse(t.getNext(), typ);
            if (_next != null) {
                if (_next.getEndToken().getNext() != null && com.pullenti.ner.core.BracketHelper.isBracket(_next.getEndToken().getNext(), true)) {
                    _next.setBeginToken(t);
                    _next.setEndToken(_next.getEndToken().getNext());
                    return _next;
                }
            }
        }
        if (((t instanceof com.pullenti.ner.TextToken) && t.getLengthChar() == 1 && t.chars.isLetter()) && typ == GeoTokenType.STRONG) {
            NumToken res = _new1576(t, t, tt != t, "c");
            char ch = com.pullenti.morph.LanguageHelper.getCyrForLat(((com.pullenti.ner.TextToken)com.pullenti.unisharp.Utils.cast(t, com.pullenti.ner.TextToken.class)).term.charAt(0));
            if (((int)ch) == 0) 
                ch = ((com.pullenti.ner.TextToken)com.pullenti.unisharp.Utils.cast(t, com.pullenti.ner.TextToken.class)).term.charAt(0);
            res.value = (String.valueOf(ch));
            res._correct(typ);
            return res;
        }
        if ((((t instanceof com.pullenti.ner.TextToken) && t.getLengthChar() == 1 && ((typ == GeoTokenType.STRONG || typ == GeoTokenType.ORG))) && t.chars.isLetter() && t.getNext() != null) && t.getNext().isHiphen() && (t.getNext().getNext() instanceof com.pullenti.ner.NumberToken)) {
            NumToken res = _new1576(t, t.getNext(), tt != t, "c");
            char ch = com.pullenti.morph.LanguageHelper.getCyrForLat(((com.pullenti.ner.TextToken)com.pullenti.unisharp.Utils.cast(t, com.pullenti.ner.TextToken.class)).term.charAt(0));
            if (((int)ch) == 0) 
                ch = ((com.pullenti.ner.TextToken)com.pullenti.unisharp.Utils.cast(t, com.pullenti.ner.TextToken.class)).term.charAt(0);
            res.value = (String.valueOf(ch));
            res._correct(typ);
            return res;
        }
        if (((t instanceof com.pullenti.ner.TextToken) && t.getLengthChar() == 2 && t.chars.isAllUpper()) && t.chars.isLetter() && typ == GeoTokenType.STRONG) {
            NumToken res = _new1576(t, t, tt != t, "c");
            res.value = ((com.pullenti.ner.TextToken)com.pullenti.unisharp.Utils.cast(t, com.pullenti.ner.TextToken.class)).term;
            res._correct(typ);
            if (res.getEndToken() != t) 
                return res;
        }
        return null;
    }

    private void _correct(GeoTokenType typ) {
        com.pullenti.ner.NumberToken nt = (com.pullenti.ner.NumberToken)com.pullenti.unisharp.Utils.cast(getEndToken(), com.pullenti.ner.NumberToken.class);
        if ((nt != null && (nt.getEndToken() instanceof com.pullenti.ner.TextToken) && com.pullenti.unisharp.Utils.stringsEq(((com.pullenti.ner.TextToken)com.pullenti.unisharp.Utils.cast(nt.getEndToken(), com.pullenti.ner.TextToken.class)).term, "Е")) && nt.getEndToken().getPrevious() == nt.getBeginToken() && !nt.getEndToken().isWhitespaceBefore()) 
            value += "Е";
        if ((nt != null && nt.typ == com.pullenti.ner.NumberSpellingType.DIGIT && (nt.getBeginToken() instanceof com.pullenti.ner.TextToken)) && ((com.pullenti.ner.TextToken)com.pullenti.unisharp.Utils.cast(nt.getBeginToken(), com.pullenti.ner.TextToken.class)).term.startsWith("0") && com.pullenti.unisharp.Utils.stringsNe(value, "0")) 
            value = "0" + value;
        com.pullenti.ner.Token t = getEndToken().getNext();
        if (t == null || t.getWhitespacesBeforeCount() > 1) 
            return;
        if (t.isHiphen() && t.getNext() != null) {
            t = t.getNext();
            if (t.isValue("ГО", null) || t.isValue("ТИ", null)) {
                setEndToken(t);
                t = t.getNext();
            }
        }
        if (t == null) 
            return;
        if (t.isValue2("ОЧЕРЕДЬ", "ОСВОЕНИЕ") || t.isValue2("ЧАСТЬ", "КОНТУРА")) {
            setEndToken(t.getNext());
            t = t.getNext().getNext();
            hasPrefix = true;
            hasSpecWord = true;
            if (t == null || t.getWhitespacesBeforeCount() > 1) 
                return;
        }
        if ((t.isValue("ОТДЕЛЕНИЕ", null) || t.isValue("КОНТУР", null) || t.isValue("ПОДЪЕМ", null)) || t.isValue("ОЧЕРЕДЬ", null) || ((t.isValue("НАДЕЛ", null) && typ == GeoTokenType.ORG))) {
            miscType = t.getNormalCaseText(com.pullenti.morph.MorphClass.NOUN, com.pullenti.morph.MorphNumber.UNDEFINED, com.pullenti.morph.MorphGender.UNDEFINED, false).toLowerCase();
            setEndToken(t);
            t = t.getNext();
            hasPrefix = true;
            hasSpecWord = true;
            if (t == null || t.getWhitespacesBeforeCount() > 1) 
                return;
        }
        if (t.isHiphen() && t.getNext() != null && ((t.getNext().isValue("Я", null) || t.getNext().isValue("ТИ", null) || t.getNext().isValue("ГО", null)))) {
            setEndToken(t.getNext());
            t = this.getEndToken().getNext();
            if (t == null || t.getWhitespacesBeforeCount() > 1) 
                return;
        }
        if ((getEndToken() instanceof com.pullenti.ner.NumberToken) && getEndToken().getLengthChar() == 2) {
            com.pullenti.ner.Token tt = t;
            if (tt.isCharOf(".:+") && tt.getNext() != null) 
                tt = tt.getNext();
            if (((tt instanceof com.pullenti.ner.NumberToken) && ((com.pullenti.ner.NumberToken)com.pullenti.unisharp.Utils.cast(tt, com.pullenti.ner.NumberToken.class)).typ == com.pullenti.ner.NumberSpellingType.DIGIT && ((com.pullenti.ner.NumberToken)com.pullenti.unisharp.Utils.cast(tt, com.pullenti.ner.NumberToken.class)).getLengthChar() == 2) && tt.getNext() != null) {
                com.pullenti.ner.Token ttt = tt.getNext();
                if (ttt.isCharOf(".:") && ttt.getNext() != null) 
                    ttt = ttt.getNext();
                boolean isKv = false;
                for (com.pullenti.ner.Token tt0 = getBeginToken().getPrevious(); tt0 != null; tt0 = tt0.getPrevious()) {
                    if (tt0.isValue("КВАРТАЛ", null) || tt0.isValue("КВ", null)) {
                        isKv = true;
                        break;
                    }
                    else if (tt0.getLengthChar() > 1 || !(tt0 instanceof com.pullenti.ner.TextToken)) 
                        break;
                }
                if ((ttt instanceof com.pullenti.ner.NumberToken) && ((((com.pullenti.ner.NumberToken)com.pullenti.unisharp.Utils.cast(ttt, com.pullenti.ner.NumberToken.class)).getLengthChar() == 6 || ((com.pullenti.ner.NumberToken)com.pullenti.unisharp.Utils.cast(ttt, com.pullenti.ner.NumberToken.class)).getLengthChar() == 7)) && ((com.pullenti.ner.NumberToken)com.pullenti.unisharp.Utils.cast(ttt, com.pullenti.ner.NumberToken.class)).typ == com.pullenti.ner.NumberSpellingType.DIGIT) {
                    value = (value + ":" + tt.getSourceText() + ":" + ttt.getSourceText());
                    setEndToken(ttt);
                    ttt = ttt.getNext();
                    isCadasterNumber = true;
                    if (ttt != null && ttt.isCharOf(".:") && (ttt.getNext() instanceof com.pullenti.ner.NumberToken)) {
                        value = (value + ":" + ttt.getNext().getSourceText());
                        setEndToken(ttt.getNext());
                    }
                }
                else if ((ttt instanceof com.pullenti.ner.NumberToken) && isKv) {
                    StringBuilder tmp = new StringBuilder();
                    tmp.append(value).append(":").append(tt.getSourceText()).append(":").append(ttt.getSourceText());
                    com.pullenti.ner.Token t1 = ttt;
                    for (ttt = ttt.getNext(); ttt != null; ttt = ttt.getNext()) {
                        if (ttt instanceof com.pullenti.ner.NumberToken) {
                            tmp.append(ttt.getSourceText());
                            t1 = ttt;
                            continue;
                        }
                        if (ttt.isChar(':') && (ttt.getNext() instanceof com.pullenti.ner.NumberToken)) {
                            tmp.append(":").append(ttt.getNext().getSourceText());
                            t1 = ttt.getNext();
                            break;
                        }
                        break;
                    }
                    if (tmp.length() >= 7) {
                        value = tmp.toString();
                        setEndToken(t1);
                        isCadasterNumber = true;
                    }
                }
            }
        }
        if (isCadasterNumber) 
            return;
        for (t = this.getEndToken().getNext(); t != null; t = t.getNext()) {
            boolean isDrob = false;
            boolean isHiph = false;
            boolean isPlus = false;
            boolean brAfter = false;
            if (((t.isHiphen() || t.isChar('_'))) && !t.isWhitespaceAfter() && t.getNext() != null) {
                isHiph = true;
                t = t.getNext();
            }
            else if (t.isCharOf("\\/") && !t.isWhitespaceAfter() && t.getNext() != null) {
                if (typ == GeoTokenType.TOSLASH) 
                    return;
                isDrob = true;
                t = t.getNext();
            }
            else if (t.isCharOf("+") && !t.isWhitespaceAfter() && t.getNext() != null) {
                isPlus = true;
                t = t.getNext();
            }
            else if (t.isValue("ДРОБЬ", null) && t.getNext() != null) {
                isDrob = true;
                t = t.getNext();
            }
            else if (com.pullenti.ner.core.BracketHelper.isBracket(t, false)) {
                if ((((t.getNext() instanceof com.pullenti.ner.NumberToken) || (((t.getNext() instanceof com.pullenti.ner.TextToken) && t.getNext().chars.isLetter() && t.getNext().getLengthChar() == 1)))) && t.getNext().getNext() != null && com.pullenti.ner.core.BracketHelper.isBracket(t.getNext().getNext(), false)) {
                    t = t.getNext();
                    brAfter = true;
                }
                else {
                    com.pullenti.ner.NumberToken lat0 = com.pullenti.ner.core.NumberHelper.tryParseRoman(t.getNext());
                    if (lat0 != null && lat0.getEndToken().getNext() != null && lat0.getEndToken().getNext().isChar(')')) {
                        t = t.getNext();
                        brAfter = true;
                    }
                }
            }
            char templ0 = template.charAt(template.length() - 1);
            if (t instanceof com.pullenti.ner.NumberToken) {
                com.pullenti.ner.NumberToken num = (com.pullenti.ner.NumberToken)com.pullenti.unisharp.Utils.cast(t, com.pullenti.ner.NumberToken.class);
                if (num.typ != com.pullenti.ner.NumberSpellingType.DIGIT) 
                    break;
                if (com.pullenti.unisharp.Utils.stringsEq(template, "c") && !num.isWhitespaceBefore()) {
                    value = (num.getValue() + value);
                    template = "cn";
                    setEndToken(t);
                    continue;
                }
                if (isHiph && ((templ0 != 'n' || typ == GeoTokenType.ORG))) {
                }
                else if (isDrob || brAfter) {
                }
                else if (!t.isWhitespaceBefore()) {
                }
                else 
                    break;
                String val = num.getValue();
                if (!num.getMorph()._getClass().isAdjective()) 
                    val = num.getSourceText();
                value = (value + (isPlus ? "+" : (isDrob || brAfter ? "/" : (templ0 == 'c' ? "" : "-"))) + val);
                template += "n";
                if (brAfter) 
                    t = t.getNext();
                setEndToken(t);
                continue;
            }
            if (t instanceof com.pullenti.ner.TextToken) {
                if (isHiph) {
                    if (t.isValue("Й", null)) {
                        setEndToken(t);
                        break;
                    }
                }
                nt = com.pullenti.ner.core.NumberHelper.tryParseRoman(t);
                if (nt != null && com.pullenti.unisharp.Utils.stringsNe(nt.getValue(), "100") && com.pullenti.unisharp.Utils.stringsNe(nt.getValue(), "10")) {
                    value = (value + (isDrob || brAfter ? '/' : '-') + nt.getValue());
                    template += "l";
                    t = nt.getEndToken();
                    if (brAfter) 
                        t = t.getNext();
                    setEndToken(t);
                    continue;
                }
            }
            if ((t instanceof com.pullenti.ner.TextToken) && t.getLengthChar() == 1 && t.chars.isLetter()) {
                boolean ok = !t.isWhitespaceBefore() || t.isNewlineAfter() || ((t.getNext() != null && (t.getNext().getNext() instanceof com.pullenti.ner.NumberToken) && ((t.getNext().isComma() || t.getNext().isCharOf("\\/")))));
                if (!ok && t.getNext() != null && com.pullenti.ner.address.internal.StreetItemToken.checkKeyword(t.getNext())) 
                    ok = true;
                if ((!ok && ((t.getNext() == null || t.getNext().isComma())) && typ == GeoTokenType.STREET) && Character.isDigit(value.charAt(value.length() - 1)) && MiscLocationHelper.isUserParamAddress(t)) {
                    com.pullenti.ner.address.internal.AddressItemToken ait = com.pullenti.ner.address.internal.AddressItemToken.tryParsePureItem(t, null, null);
                    if (ait == null) {
                        if (!com.pullenti.ner.address.internal.StreetItemToken.checkKeyword(t)) 
                            ok = true;
                    }
                }
                if (ok) {
                    if (templ0 == 'n') {
                    }
                    else if (templ0 == 'l' && ((isHiph || isDrob))) {
                    }
                    else 
                        break;
                    char ch = com.pullenti.morph.LanguageHelper.getCyrForLat(((com.pullenti.ner.TextToken)com.pullenti.unisharp.Utils.cast(t, com.pullenti.ner.TextToken.class)).term.charAt(0));
                    if (((int)ch) == 0) 
                        ch = ((com.pullenti.ner.TextToken)com.pullenti.unisharp.Utils.cast(t, com.pullenti.ner.TextToken.class)).term.charAt(0);
                    value = (value + ch);
                    template += "c";
                    if (brAfter) 
                        t = t.getNext();
                    setEndToken(t);
                    continue;
                }
            }
            break;
        }
    }

    public static char _correctChar(char v) {
        if (v == 'A' || v == 'А') 
            return 'А';
        if (v == 'Б' || v == 'Г') 
            return v;
        if (v == 'B' || v == 'В') 
            return 'В';
        if (v == 'C' || v == 'С') 
            return 'С';
        if (v == 'D' || v == 'Д') 
            return 'Д';
        if (v == 'E' || v == 'Е') 
            return 'Е';
        if (v == 'H' || v == 'Н') 
            return 'Н';
        if (v == 'K' || v == 'К') 
            return 'К';
        return (char)0;
    }

    private static String _correctCharToken(com.pullenti.ner.Token t) {
        com.pullenti.ner.TextToken tt = (com.pullenti.ner.TextToken)com.pullenti.unisharp.Utils.cast(t, com.pullenti.ner.TextToken.class);
        if (tt == null) 
            return null;
        String v = tt.term;
        if (v.length() == 1) {
            char corr = _correctChar(v.charAt(0));
            if (corr != ((char)0)) 
                return (String.valueOf(corr));
            if (t.chars.isCyrillicLetter()) 
                return v;
        }
        if (v.length() == 2) {
            if (t.chars.isCyrillicLetter()) 
                return v;
            char corr = _correctChar(v.charAt(0));
            char corr2 = _correctChar(v.charAt(1));
            if (corr != ((char)0) && corr2 != ((char)0)) 
                return (String.valueOf(corr) + corr2);
        }
        return null;
    }

    public static NumToken _new1576(com.pullenti.ner.Token _arg1, com.pullenti.ner.Token _arg2, boolean _arg3, String _arg4) {
        NumToken res = new NumToken(_arg1, _arg2);
        res.hasPrefix = _arg3;
        res.template = _arg4;
        return res;
    }

    public static NumToken _new1578(com.pullenti.ner.Token _arg1, com.pullenti.ner.Token _arg2, boolean _arg3) {
        NumToken res = new NumToken(_arg1, _arg2);
        res.hasPrefix = _arg3;
        return res;
    }
    public NumToken() {
        super();
    }
}
