package org.bdware.sc.crdt.planning;

public class PlanningWith0Expansivity extends SharableNetworkPlanning {
    public PlanningWith0Expansivity(String[] nodeIds, int[] writers, int[] readers, long maxDelay,
            int bandwidthDownload, int bandwidthUpload, int dataSize) {
        this.nodeIds = nodeIds;
        this.writers = writers;
        this.readers = readers;
        this.maxDelay = maxDelay;
        this.bandwidthDownload = bandwidthDownload;
        this.bandwidthUpload = bandwidthUpload;
        this.dataSize = dataSize;
        this.totalCountW = writers.length;
        this.totalCountR = readers.length;
    }

    public boolean writerTreeConstraint() {
        if (frequencySyncW > 0) {
            double common = frequencySyncW * dataSize;
            // 非叶子节点下载带宽
            boolean result1 = bandwidthDownload >= common * treeDegreeW;
            // 非根节点上行带宽
            boolean result2 = bandwidthUpload >= common;
            return result1 && result2;
        }
        return true;
    }

    public boolean writer2ReaderConstraint() {
        double common = frequencySyncWR * dataSize;
        // Writer根节点上行带宽
        boolean result1 = bandwidthUpload >= common * rootCountR;
        // Reader根节点下载带宽
        boolean result2 = bandwidthDownload >= common * rootCountW;
        return result1 && result2;
    }

    public boolean readerTreeConstraint() {
        if (frequencySyncR > 0) {
            double common = frequencySyncR * dataSize;
            // Reader非叶子节点上行带宽
            boolean result1 = bandwidthUpload >= common * treeDegreeR;
            // Reader非根节点下载带宽
            boolean result2 = bandwidthDownload >= common;
            return result1 && result2;
        }
        return true;
    }

    public void calcOptimizedResult() {
        double a = (treeHeightW - 1) * (totalCountW - rootCountW);
        double b = rootCountR * rootCountW;
        double c = (treeHeightR - 1) * (totalCountR - rootCountR);

        double A = Math.sqrt(a);
        double B = Math.sqrt(b);
        double C = Math.sqrt(c);

        wDelay = (long) (maxDelay * (A / (A + B + C)));
        w2rDelay = (long) (maxDelay * (B / (A + B + C)));
        rDelay = (long) (maxDelay * (C / (A + B + C)));

        frequencySyncW = wDelay > 0 ? (treeHeightW - 1) / wDelay : 0;
        frequencySyncR = rDelay > 0 ? (treeHeightR - 1) / rDelay : 0;
        frequencySyncWR = w2rDelay > 0 ? (1.0 / w2rDelay) : 0;

        totalData =
                (long) (dataSize * (frequencySyncW * a + frequencySyncWR * b + frequencySyncR * c));
    }
}
