/*
 * 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#.NET project. 
 * The latest version of the code is available on the site www.pullenti.ru
 */

const StringBuilder = require("./../../unisharp/StringBuilder");

const ComplexNumCompareType = require("./ComplexNumCompareType");
const SingleNumComparer = require("./SingleNumComparer");

/**
 * Сравнение номеров (функцией Process)
 */
class ComplexNumComparer {
    
    constructor() {
        this.typ = ComplexNumCompareType.UNCOMPARABLE;
        this.rank = 0;
        this.delta = 0;
        this.canFollow = false;
        this.first = null;
        this.second = null;
        this.m_Comp = new SingleNumComparer();
    }
    
    toString() {
        let res = new StringBuilder();
        if (this.rank > 0) 
            res.append(this.rank).append(": ");
        res.append(this.first);
        if (this.typ === ComplexNumCompareType.UNCOMPARABLE) 
            res.append(" ?? ");
        else if (this.typ === ComplexNumCompareType.EQUALS) 
            res.append(" == ");
        else if (this.typ === ComplexNumCompareType.LESS) 
            res.append(" < ");
        else if (this.typ === ComplexNumCompareType.GREAT) 
            res.append(" > ");
        res.append(this.second);
        if (this.delta > 0) 
            res.append(", Delt=").append(this.delta);
        if (this.canFollow) 
            res.append(", follow");
        return res.toString();
    }
    
    /**
     * Сравнить два номера
     * @param fir 
     * @param sec 
     */
    process(fir, sec) {
        this.first = fir;
        this.second = sec;
        this.typ = ComplexNumCompareType.EQUALS;
        this.delta = 0;
        this.rank = 1;
        if (fir.prefix !== sec.prefix || fir.suffix !== sec.suffix) {
            if (((fir.suffix === null && sec.suffix === ".")) || ((fir.suffix === "." && sec.suffix === null))) 
                this.rank *= 0.98;
            else 
                this.rank *= 0.8;
        }
        let i = 0;
        for (i = 0; (i < fir.nums.length) && (i < sec.nums.length); i++) {
            let n1 = fir.nums[i];
            let n2 = sec.nums[i];
            this.m_Comp.process(n1, n2);
            if (this.m_Comp.typ === ComplexNumCompareType.UNCOMPARABLE) {
                this.typ = ComplexNumCompareType.UNCOMPARABLE;
                this.rank = 0;
                return;
            }
            if (this.m_Comp.typ === ComplexNumCompareType.EQUALS && fir.nums.length === sec.nums.length) {
                this.rank *= this.m_Comp.rank;
                continue;
            }
            if ((i + 1) === fir.nums.length && (i + 1) === sec.nums.length) {
                this.typ = this.m_Comp.typ;
                this.rank *= this.m_Comp.rank;
                this.delta = this.m_Comp.delta;
            }
            else if (((i + 1) < fir.nums.length) && ((i + 1) < sec.nums.length)) {
                if (this.m_Comp.typ === ComplexNumCompareType.EQUALS) {
                    this.rank *= this.m_Comp.rank;
                    continue;
                }
                this.typ = ComplexNumCompareType.UNCOMPARABLE;
                this.rank = 0;
                break;
            }
            else if ((i + 1) === fir.nums.length) {
                if (this.m_Comp.typ === ComplexNumCompareType.EQUALS) {
                    this.typ = ComplexNumCompareType.LESS;
                    this.rank *= this.m_Comp.rank;
                    if (sec.nums.length === (fir.nums.length + 1) && sec.nums[i + 1].isOne) {
                        this.canFollow = true;
                        this.rank /= (2);
                    }
                    else 
                        this.rank /= (2);
                    break;
                }
                else if (this.m_Comp.typ === ComplexNumCompareType.LESS) {
                    this.typ = ComplexNumCompareType.UNCOMPARABLE;
                    this.rank = 0;
                    break;
                }
                else {
                    this.typ = ComplexNumCompareType.GREAT;
                    this.rank *= this.m_Comp.rank;
                    if (this.m_Comp.delta !== 1) 
                        this.rank /= (2);
                    break;
                }
            }
            else if ((i + 1) === sec.nums.length) {
                if (this.m_Comp.typ === ComplexNumCompareType.EQUALS) {
                    this.typ = ComplexNumCompareType.GREAT;
                    this.rank *= this.m_Comp.rank;
                    if (fir.nums.length === (sec.nums.length + 1) && fir.nums[i + 1].isOne) 
                        this.rank /= (2);
                    else 
                        this.rank /= (2);
                    break;
                }
                else if (this.m_Comp.typ === ComplexNumCompareType.LESS) {
                    this.typ = ComplexNumCompareType.LESS;
                    this.rank *= this.m_Comp.rank;
                    if (this.m_Comp.delta !== 1) 
                        this.rank /= (2);
                    else 
                        this.canFollow = true;
                    break;
                }
                else {
                    this.typ = ComplexNumCompareType.UNCOMPARABLE;
                    this.rank = 0;
                    break;
                }
            }
        }
    }
    
    /**
     * Выделить главную подпоследовательность верхнего уровня из последовательности номеров
     * @param nums исходная последовательность
     * @return результат или null
     */
    static getMainSequence(nums) {
        if (nums === null || (nums.length < 2)) 
            return null;
        let res = new Array();
        res.push(nums[0]);
        let cmp = new ComplexNumComparer();
        for (let i = 1; i < nums.length; i++) {
            let max = 0;
            let ii = -1;
            let num0 = res[res.length - 1];
            for (let j = i; j < nums.length; j++) {
                if (j === 40) {
                }
                cmp.process(num0, nums[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.push(nums[ii]);
        }
        if (res.length > 1) 
            return res;
        return null;
    }
}


module.exports = ComplexNumComparer