// derived from https://git.dervland.net/biglyderv/new-bigly-chat/src/branch/master/docs/stats.php
function rankCalc(result, iterations = 10, main = []) {
    let matrixe = {}
    let fng = {};
    let fnc = {};
    let frs = {};
    let msum_old = 0.001;
    let pr = {};

    let rl = Object.keys(result).length;
    for (let unn in result) {
        matrixe[unn] = {};
        matrixe[unn][unn] = 1;
        frs[unn] = result[unn].followers;
        fng[unn] = result[unn].following;
        fnc[unn] = Object.keys(fng[unn]).length;
        pr[unn] = 0.1 / rl;
    }

    for (let unn in result) {
        let fnu = frs[unn];
        for (let follow of fnu) {
            if (follow == unn) continue;
            let dst = fnc[fnu] || 0;
            matrixe[unn][follow] = 1 + 0.1 / (dst + 10);
            msum_old += matrixe[unn][follow];
        }
        for (let unn2 in result) {
            if (!matrixe[unn][unn2]) {
                matrixe[unn][unn2] = 0;
            }
        }
    }

    let mm = (process.env.matrixIterations || iterations);


    for (let i = 0; i < mm; i++) {
        let prold = pr;
        let matrixf = matrixe;

        pr = [];
        matrixe = [];
        let msum = 1;
        let intv = Math.pow(0.01 / rl, Math.pow(0.09, i / mm));
        console.log(`Completed ${i} iterations with ${intv} threshold`)

        let th = -1;
        for (let una in result) {
            th++;
            pr[una] = 0.1 / rl;
            matrixe[una] = [];
            if (frs[una].length == 0) {
                pr[una] = prold[una];
                matrixe[una] = matrixf[una];
                continue;
            }

            let ar = Object.keys(result);
            let rf = pr[una];

            for (let unb of ar) {
                let prb = prold[unb];

                matrixe[una][unb] = 0.03;

                if (prb * matrixf[una][unb] < intv || fnc[unb] == 0) {
                    let mfb = matrixf[una][unb];
                    if (isNaN(mfb) || !mfb) continue;
                    pr[una] += prb * mfb;
                    continue;
                }
                
                for (let unc in result) {
                    let mfc = matrixf[una][unc];
                    let mfb = matrixf[unc][unb];
                    if (isNaN(mfc) || isNaN(mfb) || !mfc || !mfb) continue;
                    matrixe[una][unb] += mfc * mfb;
                }

                msum += matrixe[una][unb];
                pr[una] += prb * matrixe[una][unb];


                if (main.indexOf(unb) == -1) {
                    matrixe[una][unb] *= 1.15;
                }
            }
        }


        for (let una in result) {
            if ((frs[una]).length == 0) continue;

            for (let unb in result) {
                matrixe[una][unb] *= msum_old / msum;
            }
        }

        let ov = Object.keys(pr);

        let new_sum = ov.filter(i => !isNaN(pr[i]) && main.indexOf(i) != -1).map(n => pr[n]).reduce((a, b) => a + b, 1e-9);
        let new_sum2 = ov.filter(i => !isNaN(pr[i]) && main.indexOf(i) == -1).map(n => pr[n]).reduce((a, b) => a + b, 1e-9);

        for (let unn in result) {
            if (main.indexOf(unn) == -1) {
                pr[unn] /= new_sum2 * 2;
            } else {
                pr[unn] /= new_sum * 2;
            }
        }

    }

    return pr;

}

export {
    rankCalc
}