// Path: dragonite-sdk/src/main/java/com/vecsight/dragonite/sdk/misc/DragoniteGlobalConstants.java
// public final class DragoniteGlobalConstants {
// 
//     public static final String LIBRARY_VERSION = DragoniteBuildConfig.VERSION;
// 
//     public static final byte PROTOCOL_VERSION = 2;
// 
//     public static final int MIN_SEND_WINDOW_SIZE = 20;
// 
//     public static final int ACK_INTERVAL_MS = 10;
// 
//     public static final int MAX_FAST_RESEND_COUNT = 3;
// 
//     public static final int MAX_SLOW_RESEND_MULT = 4;
// 
//     public static final int INIT_RTT_MS = 200, RTT_MAX_VARIATION_MS = 200, RTT_UPDATE_INTERVAL_MS = 100, RTT_RESEND_CORRECTION_INTERVAL_MS = 2000;
// 
//     public static final int DEV_RTT_MULT = 4;
// 
//     public static final float RTT_RESENDED_REFRESH_MAX_MULT = 1.5f;
// 
//     public static final int MIN_CLOSE_WAIT_MS = 100, CLOSE_WAIT_RTT_MULT = 4;
// 
//     public static final int WEB_PANEL_PORT = 8000;
// 
// }
// 
// Path: dragonite-sdk/src/main/java/com/vecsight/dragonite/sdk/misc/NumUtils.java
// public final class NumUtils {
// 
//     public static long min(final long l1, final long l2) {
//         return l1 < l2 ? l1 : l2;
//     }
// 
//     public static long max(final long l1, final long l2) {
//         return l1 > l2 ? l1 : l2;
//     }
// 
//     public static int min(final int i1, final int i2) {
//         return i1 < i2 ? i1 : i2;
//     }
// 
//     public static int max(final int i1, final int i2) {
//         return i1 > i2 ? i1 : i2;
//     }
// 
// }


import com.vecsight.dragonite.sdk.misc.DragoniteGlobalConstants;
import com.vecsight.dragonite.sdk.misc.NumUtils;
/*
 * The Dragonite Project
 * -------------------------
 * See the LICENSE file in the root directory for license information.
 */


package com.vecsight.dragonite.sdk.socket;


public class RTTEstimator {

    private final static float estimatedRTTUpdateFactor = 0.125f, devRTTUpdateFactor = 0.25f;

    private final ConnectionState state;

    private long estimatedRTT = DragoniteGlobalConstants.INIT_RTT_MS, devRTT;

    private long lastUpdate = 0;

    private int continuousResendCount = 0;

    public RTTEstimator(final ConnectionState state) {
        this.state = state;
    }

    public void pushStat(final MessageStat stat) {
        //System.out.println(stat);
        if (stat.isExist()) {
            final long currentTime = System.currentTimeMillis();
            /*if (currentTime - lastRefresh >= DragoniteGlobalConstants.rttRefreshIntervalMS) {
                lastRefresh = System.currentTimeMillis();
                if (stat.isResended()) {
                    long maxCRTT = (long) (estimatedRTT * DragoniteGlobalConstants.RTT_RESENDED_REFRESH_MAX_MULT);
                    setRTT(NumUtils.min(stat.getRTT(), maxCRTT), 0);
                }
            }*/
            if (currentTime - lastUpdate >= DragoniteGlobalConstants.RTT_UPDATE_INTERVAL_MS) {
                lastUpdate = currentTime;

                //System.out.println(stat.toString());

                if (!stat.isResended()) {
                    continuousResendCount = 0;
                    clampSetRTT((long) ((1 - estimatedRTTUpdateFactor) * estimatedRTT + estimatedRTTUpdateFactor * stat.getRTT()),
                            (long) ((1 - devRTTUpdateFactor) * devRTT + devRTTUpdateFactor * Math.abs(stat.getRTT() - estimatedRTT)));
                } else {
                    continuousResendCount++;
                    if (continuousResendCount > (DragoniteGlobalConstants.RTT_RESEND_CORRECTION_INTERVAL_MS / DragoniteGlobalConstants.RTT_UPDATE_INTERVAL_MS)) {
                        final long maxCRTT = (long) (estimatedRTT * DragoniteGlobalConstants.RTT_RESENDED_REFRESH_MAX_MULT);
// Path: dragonite-sdk/src/main/java/com/vecsight/dragonite/sdk/misc/DragoniteGlobalConstants.java
// public final class DragoniteGlobalConstants {
// 
//     public static final String LIBRARY_VERSION = DragoniteBuildConfig.VERSION;
// 
//     public static final byte PROTOCOL_VERSION = 2;
// 
//     public static final int MIN_SEND_WINDOW_SIZE = 20;
// 
//     public static final int ACK_INTERVAL_MS = 10;
// 
//     public static final int MAX_FAST_RESEND_COUNT = 3;
// 
//     public static final int MAX_SLOW_RESEND_MULT = 4;
// 
//     public static final int INIT_RTT_MS = 200, RTT_MAX_VARIATION_MS = 200, RTT_UPDATE_INTERVAL_MS = 100, RTT_RESEND_CORRECTION_INTERVAL_MS = 2000;
// 
//     public static final int DEV_RTT_MULT = 4;
// 
//     public static final float RTT_RESENDED_REFRESH_MAX_MULT = 1.5f;
// 
//     public static final int MIN_CLOSE_WAIT_MS = 100, CLOSE_WAIT_RTT_MULT = 4;
// 
//     public static final int WEB_PANEL_PORT = 8000;
// 
// }
// 
// Path: dragonite-sdk/src/main/java/com/vecsight/dragonite/sdk/misc/NumUtils.java
// public final class NumUtils {
// 
//     public static long min(final long l1, final long l2) {
//         return l1 < l2 ? l1 : l2;
//     }
// 
//     public static long max(final long l1, final long l2) {
//         return l1 > l2 ? l1 : l2;
//     }
// 
//     public static int min(final int i1, final int i2) {
//         return i1 < i2 ? i1 : i2;
//     }
// 
//     public static int max(final int i1, final int i2) {
//         return i1 > i2 ? i1 : i2;
//     }
// 
// }


// Path: dragonite-sdk/src/main/java/com/vecsight/dragonite/sdk/socket/RTTEstimator.java
import com.vecsight.dragonite.sdk.misc.DragoniteGlobalConstants;
import com.vecsight.dragonite.sdk.misc.NumUtils;

/*
 * The Dragonite Project
 * -------------------------
 * See the LICENSE file in the root directory for license information.
 */


package com.vecsight.dragonite.sdk.socket;


public class RTTEstimator {

    private final static float estimatedRTTUpdateFactor = 0.125f, devRTTUpdateFactor = 0.25f;

    private final ConnectionState state;

    private long estimatedRTT = DragoniteGlobalConstants.INIT_RTT_MS, devRTT;

    private long lastUpdate = 0;

    private int continuousResendCount = 0;

    public RTTEstimator(final ConnectionState state) {
        this.state = state;
    }

    public void pushStat(final MessageStat stat) {
        //System.out.println(stat);
        if (stat.isExist()) {
            final long currentTime = System.currentTimeMillis();
            /*if (currentTime - lastRefresh >= DragoniteGlobalConstants.rttRefreshIntervalMS) {
                lastRefresh = System.currentTimeMillis();
                if (stat.isResended()) {
                    long maxCRTT = (long) (estimatedRTT * DragoniteGlobalConstants.RTT_RESENDED_REFRESH_MAX_MULT);
                    setRTT(NumUtils.min(stat.getRTT(), maxCRTT), 0);
                }
            }*/
            if (currentTime - lastUpdate >= DragoniteGlobalConstants.RTT_UPDATE_INTERVAL_MS) {
                lastUpdate = currentTime;

                //System.out.println(stat.toString());

                if (!stat.isResended()) {
                    continuousResendCount = 0;
                    clampSetRTT((long) ((1 - estimatedRTTUpdateFactor) * estimatedRTT + estimatedRTTUpdateFactor * stat.getRTT()),
                            (long) ((1 - devRTTUpdateFactor) * devRTT + devRTTUpdateFactor * Math.abs(stat.getRTT() - estimatedRTT)));
                } else {
                    continuousResendCount++;
                    if (continuousResendCount > (DragoniteGlobalConstants.RTT_RESEND_CORRECTION_INTERVAL_MS / DragoniteGlobalConstants.RTT_UPDATE_INTERVAL_MS)) {
                        final long maxCRTT = (long) (estimatedRTT * DragoniteGlobalConstants.RTT_RESENDED_REFRESH_MAX_MULT);
                        final long tmpRTT = NumUtils.min(stat.getRTT(), maxCRTT);