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

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

    public java.util.ArrayList<ChemicalToken> subtokens = null;

    public char bracket = (char)0;

    public boolean hiphenBefore;

    public String name = null;

    public java.util.ArrayList<ChemicalUnit> items = null;

    public int num;

    public boolean isDoubt;

    @Override
    public String toString() {
        StringBuilder res = new StringBuilder();
        if (hiphenBefore) 
            res.append("-");
        if (name != null) 
            res.append(name);
        if (subtokens != null) {
            res.append(bracket);
            for (ChemicalToken s : subtokens) {
                res.append(s.toString());
            }
            res.append((bracket == '[' ? ']' : ')'));
        }
        if (items != null && name == null) {
            for (ChemicalUnit u : items) {
                res.append(u.mnem.charAt(0));
                if (u.mnem.length() > 1) 
                    res.append(Character.toLowerCase(u.mnem.charAt(1)));
            }
        }
        if (num > 0) 
            res.append(num);
        return res.toString();
    }

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

    public static java.util.ArrayList<ChemicalToken> tryParseList(com.pullenti.ner.Token t, int lev) {
        initialize();
        java.util.ArrayList<ChemicalToken> res = null;
        for (com.pullenti.ner.Token tt = t; tt != null; tt = tt.getNext()) {
            ChemicalToken it = tryParse(tt, (res == null || res.size() == 0 ? null : res.get(res.size() - 1)), lev);
            if (it != null) {
                if (res == null) 
                    res = new java.util.ArrayList<ChemicalToken>();
                if (it.name == null && res.size() > 0 && it.isWhitespaceBefore()) {
                    if (res.get(res.size() - 1).name == null) 
                        break;
                }
                res.add(it);
                tt = it.getEndToken();
                continue;
            }
            if ((tt.isValue("ИЛИ", null) && res != null && res.size() == 1) && res.get(0).name != null) {
                it = tryParse(tt.getNext(), null, lev);
                if (it != null && it.name != null) {
                    res.add(it);
                    tt = it.getEndToken();
                    continue;
                }
            }
            break;
        }
        return res;
    }

    private static ChemicalToken tryParse(com.pullenti.ner.Token t, ChemicalToken prev, int lev) {
        if (lev > 3) 
            return null;
        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;
        if (tt.isCharOf("[(")) {
            java.util.ArrayList<ChemicalToken> li = tryParseList(tt.getNext(), lev + 1);
            if (li == null || li.size() == 0) 
                return null;
            com.pullenti.ner.Token ee = li.get(li.size() - 1).getEndToken().getNext();
            if (ee == null || !ee.isCharOf("])")) 
                return null;
            ChemicalToken ct = _new538(t, ee, li);
            if (tt.isChar('(')) 
                ct.bracket = '(';
            else 
                ct.bracket = '[';
            ct._addNum();
            return ct;
        }
        if (tt.isHiphen()) {
            if (prev == null) 
                return null;
            boolean mustBeName = false;
            if (tt.isWhitespaceBefore() || tt.isWhitespaceAfter()) {
                if (prev.name != null) {
                }
                else 
                    mustBeName = true;
            }
            ChemicalToken ct = tryParse(tt.getNext(), null, lev + 1);
            if (ct == null) 
                return null;
            if (mustBeName && ct.name == null) 
                return null;
            if (prev.name != null && ct.name != null) 
                return null;
            if (prev.name == null && ct.name == null) 
                ct.hiphenBefore = true;
            ct.setBeginToken(tt);
            return ct;
        }
        if (tt.chars.isLetter() && !tt.chars.isAllLower()) {
            String str = tt.getSourceText();
            java.util.ArrayList<ChemicalUnit> cus = null;
            int i;
            for (i = 0; i < str.length(); i++) {
                char ch0 = str.charAt(i);
                if (Character.isLowerCase(ch0)) 
                    break;
                if (((int)ch0) > 0x80) {
                    ch0 = com.pullenti.morph.LanguageHelper.getLatForCyr(ch0);
                    if (((int)ch0) == 0) 
                        break;
                }
                String mnem = (String.valueOf(ch0));
                if (((i + 1) < str.length()) && Character.isLowerCase(str.charAt(i + 1))) {
                    char ch1 = Character.toUpperCase(str.charAt(i + 1));
                    if (((int)ch1) > 0x80) {
                        ch1 = com.pullenti.morph.LanguageHelper.getLatForCyr(ch1);
                        if (((int)ch1) == 0) 
                            break;
                    }
                    mnem = (String.valueOf(ch0) + ch1);
                    i++;
                }
                ChemicalUnit cu;
                com.pullenti.unisharp.Outargwrapper<ChemicalUnit> wrapcu539 = new com.pullenti.unisharp.Outargwrapper<ChemicalUnit>();
                boolean inoutres540 = com.pullenti.unisharp.Utils.tryGetValue(m_UnitsByMnem, mnem, wrapcu539);
                cu = wrapcu539.value;
                if (!inoutres540) 
                    break;
                if (cus == null) 
                    cus = new java.util.ArrayList<ChemicalUnit>();
                cus.add(cu);
            }
            if (i >= str.length() && cus != null) {
                ChemicalToken ct = _new541(t, t, cus);
                ct._addNum();
                if (ct.num == 0 && ((!t.getMorphClassInDictionary().isUndefined() || (t.getLengthChar() < 2)))) 
                    ct.isDoubt = true;
                for (int ii = 0; ii < (ct.items.size() - 1); ii++) {
                    for (int jj = ii + 1; jj < ct.items.size(); jj++) {
                        if (ct.items.get(ii) == ct.items.get(jj)) 
                            ct.isDoubt = true;
                    }
                }
                if (ct.items.size() > 6) 
                    ct.isDoubt = true;
                return ct;
            }
        }
        com.pullenti.ner.Token tt1 = null;
        for (t = tt; t != null; t = t.getNext()) {
            com.pullenti.ner.core.TerminToken tok = m_Termins.tryParse(t, com.pullenti.ner.core.TerminParseAttr.NO);
            if (tok != null) {
                tt1 = (t = tok.getEndToken());
                continue;
            }
            com.pullenti.ner.core.NounPhraseToken npt = com.pullenti.ner.core.NounPhraseHelper.tryParse(t, com.pullenti.ner.core.NounPhraseParseAttr.NO, 0, null);
            if (npt != null) {
                boolean ok = false;
                for (com.pullenti.ner.Token ttt = npt.getBeginToken(); ttt != null && ttt.getEndChar() <= npt.getEndChar(); ttt = ttt.getNext()) {
                    if (_canBePartName((com.pullenti.ner.TextToken)com.pullenti.unisharp.Utils.cast(ttt, com.pullenti.ner.TextToken.class))) 
                        ok = true;
                }
                if (ok) {
                    tt1 = (t = npt.getEndToken());
                    continue;
                }
            }
            if (_canBePartName((com.pullenti.ner.TextToken)com.pullenti.unisharp.Utils.cast(t, com.pullenti.ner.TextToken.class))) {
                tt1 = t;
                continue;
            }
            break;
        }
        if (tt1 != null) {
            ChemicalToken ci = new ChemicalToken(tt, tt1);
            ci.name = com.pullenti.ner.core.MiscHelper.getTextValue(tt, tt1, com.pullenti.ner.core.GetTextAttr.FIRSTNOUNGROUPTONOMINATIVE);
            if (tt == tt1) {
                ci.isDoubt = true;
                com.pullenti.ner.core.TerminToken tok = m_Termins.tryParse(tt, com.pullenti.ner.core.TerminParseAttr.NO);
                if (tok != null && (tok.termin.tag instanceof ChemicalUnit)) 
                    ci.isDoubt = false;
            }
            if (tt.getPrevious() != null && tt.getPrevious().isValue("ФОРМУЛА", null)) 
                ci.isDoubt = false;
            return ci;
        }
        return null;
    }

    private static boolean _canBePartName(com.pullenti.ner.TextToken t) {
        if (t == null) 
            return false;
        com.pullenti.ner.core.TerminToken tok = m_Termins.tryParse(t, com.pullenti.ner.core.TerminParseAttr.NO);
        if (tok != null) 
            return true;
        String val = t.getNormalCaseText(null, com.pullenti.morph.MorphNumber.UNDEFINED, com.pullenti.morph.MorphGender.UNDEFINED, false);
        com.pullenti.morph.MorphClass mc = t.getMorphClassInDictionary();
        if (((((val.endsWith("ИД") || val.endsWith("ОЛ") || val.endsWith("КИСЬ")) || val.endsWith("ТАН") || val.endsWith("ОЗА")) || val.endsWith("ИН") || val.endsWith("АТ")) || val.endsWith("СИД") || val.startsWith("ДИ")) || val.startsWith("ТРИ") || val.startsWith("ЧЕТЫР")) {
            if (mc.isUndefined()) 
                return true;
            if ((((val.endsWith("КИСЬ") || val.endsWith("ТОРИД") || val.endsWith("ЦЕТАТ")) || val.endsWith("РАЗИН") || val.endsWith("КСИД")) || val.endsWith("ФИД") || val.endsWith("РИД")) || val.endsWith("ОНАТ")) 
                return true;
        }
        if ((((((val.startsWith("ГЕКСА") || val.startsWith("ДЕКА") || val.startsWith("ТЕТРА")) || val.startsWith("ПЕНТА") || val.startsWith("ГЕПТА")) || val.startsWith("ОКТА") || val.startsWith("НОНА")) || val.startsWith("УНДЕКА") || val.startsWith("ДОДЕКА")) || val.startsWith("ЭЙКОЗА") || val.startsWith("ГЕКТА")) || val.startsWith("КИЛА") || val.startsWith("МИРИА")) 
            return true;
        return false;
    }

    public static com.pullenti.ner.chemical.ChemicalFormulaReferent createReferent(java.util.ArrayList<ChemicalToken> li) {
        if (li.size() == 1) {
            if (li.get(0).isDoubt) 
                return null;
            if (((int)li.get(0).bracket) != 0) 
                return null;
            if (((li.get(0).items != null && li.get(0).items.size() == 1)) || (((li.get(0).getLengthChar() < 5) || li.get(0).isDoubt))) {
                boolean ok = false;
                int cou = 40;
                for (com.pullenti.ner.Token tt = li.get(0).getBeginToken().getPrevious(); tt != null && cou > 0; tt = tt.getPrevious(),cou--) {
                    if (tt.getReferent() instanceof com.pullenti.ner.chemical.ChemicalFormulaReferent) {
                        ok = true;
                        break;
                    }
                    if (m_Termins.tryParse(tt, com.pullenti.ner.core.TerminParseAttr.NO) != null || m_Keywords.tryParse(tt, com.pullenti.ner.core.TerminParseAttr.NO) != null) {
                        ok = true;
                        break;
                    }
                }
                cou = 40;
                if (!ok) {
                    for (com.pullenti.ner.Token tt = li.get(li.size() - 1).getEndToken().getNext(); tt != null && cou > 0; tt = tt.getNext(),cou--) {
                        if (tt.getReferent() instanceof com.pullenti.ner.chemical.ChemicalFormulaReferent) {
                            ok = true;
                            break;
                        }
                        if (m_Termins.tryParse(tt, com.pullenti.ner.core.TerminParseAttr.NO) != null || m_Keywords.tryParse(tt, com.pullenti.ner.core.TerminParseAttr.NO) != null) {
                            ok = true;
                            break;
                        }
                    }
                }
                if (!ok) 
                    return null;
            }
        }
        com.pullenti.ner.chemical.ChemicalFormulaReferent res = new com.pullenti.ner.chemical.ChemicalFormulaReferent();
        String val = null;
        for (int i = 0; i < li.size(); i++) {
            if (li.get(i).name != null) 
                res.addSlot(com.pullenti.ner.chemical.ChemicalFormulaReferent.ATTR_NAME, li.get(i).name, false, 0);
            else if (val == null) 
                val = li.get(i).toString();
            else 
                val += li.get(i).toString();
        }
        if (val != null) 
            res.setValue(val);
        return res;
    }

    private void _addNum() {
        if (getEndToken().isWhitespaceAfter()) 
            return;
        if (getEndToken().getNext() instanceof com.pullenti.ner.NumberToken) {
            setEndToken(this.getEndToken().getNext());
            num = ((com.pullenti.ner.NumberToken)com.pullenti.unisharp.Utils.cast(this.getEndToken(), com.pullenti.ner.NumberToken.class)).getIntValue();
            return;
        }
        if (getEndToken().getNext().getLengthChar() == 1) {
            for (int i = 2; i <= 9; i++) {
                if (getEndToken().getNext().isChar((char)((0x2080 + i)))) {
                    setEndToken(this.getEndToken().getNext());
                    num = 2;
                    return;
                }
            }
        }
        if ((getEndToken().getNext() != null && getEndToken().getNext().isCharOf("<[") && (getEndToken().getNext().getNext() instanceof com.pullenti.ner.NumberToken)) && getEndToken().getNext().getNext().getNext() != null && getEndToken().getNext().getNext().getNext().isCharOf(">]")) {
            num = ((com.pullenti.ner.NumberToken)com.pullenti.unisharp.Utils.cast(this.getEndToken().getNext().getNext(), com.pullenti.ner.NumberToken.class)).getIntValue();
            setEndToken(this.getEndToken().getNext().getNext().getNext());
            return;
        }
    }

    public static void initialize() {
        if (UNITS != null) 
            return;
        m_Termins = new com.pullenti.ner.core.TerminCollection();
        m_Keywords = new com.pullenti.ner.core.TerminCollection();
        m_UnitsByMnem = new java.util.HashMap<String, ChemicalUnit>();
        UNITS = new java.util.ArrayList<ChemicalUnit>();
        String all = (((((("Водород,H;Гелий,He;Литий,Li;Бериллий,Be;Бор,B;Углерод,C;Азот,N;Кислород,O;Фтор,F;" + "Неон,Ne;Натрий,Na;Магний,Mg;Алюминий,Al;Кремний,Si;Фосфор,P;Сера,S;Хлор,Cl;Аргон,Ar;Калий,K;" + "Кальций,Ca;Скандий,Sc;Титан,Ti;Ванадий,V;Хром,Cr;Марганец,Mn;Железо,Fe;Кобальт,Co;Никель,Ni;") + "Медь,Cu;Цинк,Zn;Галлий,Ga;Германий,Ge;Мышьяк,As;Селен,Se;Бром,Br;Криптон,Kr;Рубидий,Rb;" + "Стронций,Sr;Иттрий,Y;Цирконий,Zr;Ниобий,Nb;Молибден,Mo;Технеций,Tc;Рутений,Ru;Родий,Rh;") + "Палладий,Pd;Серебро,Ag;Кадмий,Cd;Индий,In;Олово,Sn;Сурьма,Sb;Теллур,Te;Иод,I;Ксенон,Xe;" + "Цезий,Cs;Барий,Ba;Лантан,La;Церий,Ce;Празеодим,Pr;Неодим,Nd;Прометий,Pm;Самарий,Sm;") + "Европий,Eu;Гадолиний,Gd;Тербий,Tb;Диспрозий,Dy;Гольмий,Ho;Эрбий,Er;Тулий,Tm;Иттербий,Yb;" + "Лютеций,Lu;Гафний,Hf;Тантал,Ta;Вольфрам,W;Рений,Re;Осмий,Os;Иридий,Ir;Платина,Pt;") + "Золото,Au;Ртуть,Hg;Таллий,Tl;Свинец,Pb;Висмут,Bi;Полоний,Po;Астат,At;Радон,Rn;Франций,Fr;" + "Радий,Ra;Актиний,Ac;Торий,Th;Протактиний,Pa;Уран,U;Нептуний,Np;Плутоний,Pu;Америций,Am;") + "Кюрий,Cm;Берклий,Bk;Калифорний,Cf;Эйнштейний,Es;Фермий,Fm;Менделевий,Md;Нобелий,No;Лоуренсий,Lr;" + "Резерфордий,Rf;Дубний,Db;Сиборгий,Sg;Борий,Bh;Хассий,Hs;Мейтнерий,Mt;Дармштадтий,Ds;Рентгений,Rg;") + "Коперниций,Cn;Нихоний,Nh;Флеровий,Fl;Московий,Mc;Ливерморий,Lv;Теннессин,Ts;Оганесон,Og";
        for (String p : com.pullenti.unisharp.Utils.split(all.toUpperCase(), String.valueOf(';'), false)) {
            int i = p.indexOf(',');
            if (i < 0) 
                continue;
            ChemicalUnit ci = new ChemicalUnit(p.substring(i + 1), p.substring(0, 0 + i), null);
            UNITS.add(ci);
            m_Termins.add(com.pullenti.ner.core.Termin._new96(ci.nameCyr, ci));
            m_UnitsByMnem.put(ci.mnem, ci);
        }
        for (String s : new String[] {"КИСЛОТА", "РАСТВОР", "СПИРТ", "ВОДА", "СОЛЬ", "АММИАК", "БУТАН", "БЕНЗОЛ", "КЕРОСИН", "АМИН", "СКИПИДАР", "ОКИСЬ", "ГИДРИТ", "АММОНИЙ", "ПЕРЕКИСЬ", "КАРБОНАТ"}) {
            m_Termins.add(new com.pullenti.ner.core.Termin(s, null, false));
        }
        for (String s : new String[] {"МЕТАЛЛ", "ГАЗ", "ТОПЛИВО", "МОНОТОПЛИВО", "СМЕСЬ", "ХИМИЧЕСКИЙ", "МОЛЕКУЛА", "АТОМ", "МОЛЕКУЛЯРНЫЙ", "АТОМАРНЫЙ"}) {
            m_Keywords.add(new com.pullenti.ner.core.Termin(s, null, false));
        }
    }

    private static com.pullenti.ner.core.TerminCollection m_Termins;

    private static com.pullenti.ner.core.TerminCollection m_Keywords;

    private static java.util.HashMap<String, ChemicalUnit> m_UnitsByMnem;

    public static java.util.ArrayList<ChemicalUnit> UNITS;

    public static ChemicalToken _new538(com.pullenti.ner.Token _arg1, com.pullenti.ner.Token _arg2, java.util.ArrayList<ChemicalToken> _arg3) {
        ChemicalToken res = new ChemicalToken(_arg1, _arg2);
        res.subtokens = _arg3;
        return res;
    }

    public static ChemicalToken _new541(com.pullenti.ner.Token _arg1, com.pullenti.ner.Token _arg2, java.util.ArrayList<ChemicalUnit> _arg3) {
        ChemicalToken res = new ChemicalToken(_arg1, _arg2);
        res.items = _arg3;
        return res;
    }
    public ChemicalToken() {
        super();
    }
}
