/*
 * 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;

/**
 * Сравнение номеров (функцией Process)
 */
public class ComplexNumComparer {

    /**
     * Сюда запишется результат
     */
    public ComplexNumCompareType typ = ComplexNumCompareType.UNCOMPARABLE;

    /**
     * Ранг сравнения
     */
    public double rank;

    /**
     * Дельта между номерами, если номера сравниваемые
     */
    public int delta;

    /**
     * Это если разных уровней, но могут следовать друг за другом (1 - 1.1 - 2)
     */
    public boolean canFollow;

    /**
     * Первый сравниваемый номер
     */
    public ComplexNumToken first;

    /**
     * Второй сравниваемый номер
     */
    public ComplexNumToken second;

    @Override
    public String toString() {
        StringBuilder res = new StringBuilder();
        if (rank > 0) 
            res.append(rank).append(": ");
        res.append(first);
        if (typ == ComplexNumCompareType.UNCOMPARABLE) 
            res.append(" ?? ");
        else if (typ == ComplexNumCompareType.EQUALS) 
            res.append(" == ");
        else if (typ == ComplexNumCompareType.LESS) 
            res.append(" < ");
        else if (typ == ComplexNumCompareType.GREAT) 
            res.append(" > ");
        res.append(second);
        if (delta > 0) 
            res.append(", Delt=").append(delta);
        if (canFollow) 
            res.append(", follow");
        return res.toString();
    }

    private SingleNumComparer m_Comp = new SingleNumComparer();

    /**
     * Сравнить два номера
     * @param fir 
     * @param sec 
     */
    public void process(ComplexNumToken fir, ComplexNumToken sec) {
        first = fir;
        second = sec;
        typ = ComplexNumCompareType.EQUALS;
        delta = 0;
        rank = 1.0;
        if (com.pullenti.unisharp.Utils.stringsNe(fir.getPrefix(), sec.getPrefix()) || com.pullenti.unisharp.Utils.stringsNe(fir.getSuffix(), sec.getSuffix())) {
            if (((fir.getSuffix() == null && com.pullenti.unisharp.Utils.stringsEq(sec.getSuffix(), "."))) || ((com.pullenti.unisharp.Utils.stringsEq(fir.getSuffix(), ".") && sec.getSuffix() == null))) 
                rank *= 0.98;
            else 
                rank *= 0.8;
        }
        int i;
        for (i = 0; (i < fir.nums.size()) && (i < sec.nums.size()); i++) {
            SingleNumToken n1 = fir.nums.get(i);
            SingleNumToken n2 = sec.nums.get(i);
            m_Comp.process(n1, n2);
            if (m_Comp.typ == ComplexNumCompareType.UNCOMPARABLE) {
                typ = ComplexNumCompareType.UNCOMPARABLE;
                rank = 0.0;
                return;
            }
            if (m_Comp.typ == ComplexNumCompareType.EQUALS && fir.nums.size() == sec.nums.size()) {
                rank *= m_Comp.rank;
                continue;
            }
            if ((i + 1) == fir.nums.size() && (i + 1) == sec.nums.size()) {
                typ = m_Comp.typ;
                rank *= m_Comp.rank;
                delta = m_Comp.delta;
            }
            else if (((i + 1) < fir.nums.size()) && ((i + 1) < sec.nums.size())) {
                if (m_Comp.typ == ComplexNumCompareType.EQUALS) {
                    rank *= m_Comp.rank;
                    continue;
                }
                typ = ComplexNumCompareType.UNCOMPARABLE;
                rank = 0.0;
                break;
            }
            else if ((i + 1) == fir.nums.size()) {
                if (m_Comp.typ == ComplexNumCompareType.EQUALS) {
                    typ = ComplexNumCompareType.LESS;
                    rank *= m_Comp.rank;
                    if (sec.nums.size() == (fir.nums.size() + 1) && sec.nums.get(i + 1).isOne()) {
                        canFollow = true;
                        rank /= (2.0);
                    }
                    else 
                        rank /= (2.0);
                    break;
                }
                else if (m_Comp.typ == ComplexNumCompareType.LESS) {
                    typ = ComplexNumCompareType.UNCOMPARABLE;
                    rank = 0.0;
                    break;
                }
                else {
                    typ = ComplexNumCompareType.GREAT;
                    rank *= m_Comp.rank;
                    if (m_Comp.delta != 1) 
                        rank /= (2.0);
                    break;
                }
            }
            else if ((i + 1) == sec.nums.size()) {
                if (m_Comp.typ == ComplexNumCompareType.EQUALS) {
                    typ = ComplexNumCompareType.GREAT;
                    rank *= m_Comp.rank;
                    if (fir.nums.size() == (sec.nums.size() + 1) && fir.nums.get(i + 1).isOne()) 
                        rank /= (2.0);
                    else 
                        rank /= (2.0);
                    break;
                }
                else if (m_Comp.typ == ComplexNumCompareType.LESS) {
                    typ = ComplexNumCompareType.LESS;
                    rank *= m_Comp.rank;
                    if (m_Comp.delta != 1) 
                        rank /= (2.0);
                    else 
                        canFollow = true;
                    break;
                }
                else {
                    typ = ComplexNumCompareType.UNCOMPARABLE;
                    rank = 0.0;
                    break;
                }
            }
        }
    }

    /**
     * Выделить главную подпоследовательность верхнего уровня из последовательности номеров
     * @param nums исходная последовательность
     * @return результат или null
     */
    public static java.util.ArrayList<ComplexNumToken> getMainSequence(java.util.ArrayList<ComplexNumToken> nums) {
        if (nums == null || (nums.size() < 2)) 
            return null;
        java.util.ArrayList<ComplexNumToken> res = new java.util.ArrayList<ComplexNumToken>();
        res.add(nums.get(0));
        ComplexNumComparer cmp = new ComplexNumComparer();
        for (int i = 1; i < nums.size(); i++) {
            double max = 0.0;
            int ii = -1;
            ComplexNumToken num0 = res.get(res.size() - 1);
            for (int j = i; j < nums.size(); j++) {
                if (j == 40) {
                }
                cmp.process(num0, nums.get(j));
                if (cmp.typ != ComplexNumCompareType.LESS) 
                    continue;
                if (cmp.delta != 1) 
                    continue;
                if (cmp.rank > max) {
                    max = cmp.rank;
                    ii = j;
                }
            }
            if (max < 0.9) 
                continue;
            i = ii;
            res.add(nums.get(ii));
        }
        if (res.size() > 1) 
            return res;
        return null;
    }
    public ComplexNumComparer() {
    }
}
