package com.easysocket.connection.reconnect;

import android.os.Handler;
import android.os.HandlerThread;

import com.easysocket.entity.SocketAddress;
import com.easysocket.interfaces.conn.IConnectionManager;
import com.easysocket.utils.LogUtil;

/**
 * Author：Alex
 * Date：2019/5/28
 * Note：默认重连器
 */
public class DefaultReConnection extends AbsReconnection {
    /**
     * 最大连接失败次数，超过可以切换到备用的服务器地址
     */
    private static final int MAX_CONNECTION_FAILED_TIMES = 10;
    /**
     * 连接失败的次数
     */
    private int connectionFailedTimes = 0;
    /**
     * 重连间隔不能小于10秒，为了避免全部客户端socket在同一时间连接服务端，间隔时间需要上下浮动50%
     */
    private long reconnectTimeDelay = 30 * 1000;
    /**
     * 重连线程
     */
    private HandlerThread handlerThread;
    /**
     * 实现延时任务的 handler
     */
    private Handler handler;

    public DefaultReConnection() {
    }

    @Override
    public synchronized void attach(IConnectionManager iConnectionManager) {
        super.attach(iConnectionManager);
        if (reconnectTimeDelay < connectionManager.getOptions().getConnectTimeout()) {
            reconnectTimeDelay = connectionManager.getOptions().getConnectTimeout();
        }
    }

    /**
     * 重连任务
     */
    private final Runnable RcConnTask = new Runnable() {
        @Override
        public void run() {
            LogUtil.d("---> 执行重连");
            if (isDetach) {
                shutDown();
                return;
            }
            // 是否可连接的
            if (!connectionManager.isConnectViable()) {
                LogUtil.d("当前条件不允许连接");
                // 尝试再次重连
                handler.postDelayed(RcConnTask, (long) (reconnectTimeDelay * (Math.random() + 0.5)));
                return;
            }
            // 重连
            connectionManager.connect();
        }
    };

    /**
     * 进行重连
     */
    private void reconnect() {
        if (handlerThread == null) {
            handlerThread = new HandlerThread("re_conn");
            handlerThread.start();
            handler = new Handler(handlerThread.getLooper());
        }
        LogUtil.d("重连间隔时间-->" + reconnectTimeDelay * (Math.random() + 0.5));
        handler.postDelayed(RcConnTask, (long) (reconnectTimeDelay * (Math.random() + 0.5)));
    }


    // 关闭重连线程
    private void shutDown() {
        if (handlerThread != null && handlerThread.isAlive()) {
            handlerThread.quit();
            handlerThread = null;
            handler = null;
        }
    }

    @Override
    public boolean equals(Object o) {
        // getClass返回Class类型的对象，比较它们的类型对象是否==，其实是比较它们是否为同一个Class创建的对象
        if (o == null || getClass() != o.getClass()) return false;
        return true;
    }

    @Override
    public void onSocketConnSuccess(SocketAddress socketAddress) {
        // 连接成功关闭重连线程
        shutDown();
    }

    @Override
    public void onSocketConnFail(SocketAddress socketAddress, boolean isNeedReconnect) {
        // 不需要重连，则关闭重连线程
        if (!isNeedReconnect) {
            shutDown();
            return;
        }
        connectionFailedTimes++;

        // 如果大于最大连接次数并且有备用host,则轮流切换两个host
        if (connectionFailedTimes > MAX_CONNECTION_FAILED_TIMES && socketAddress.getBackupAddress() != null) {
            connectionFailedTimes = 0; // 归零
            SocketAddress backupAddress = socketAddress.getBackupAddress();
            SocketAddress nowAddress = new SocketAddress(socketAddress.getIp(), socketAddress.getPort());
            backupAddress.setBackupAddress(nowAddress);
            if (connectionManager.isConnectViable()) {
                connectionManager.switchHost(backupAddress);
                // 切换主机地址，重新连接
                reconnect();
            }
        } else {
            reconnect();
        }

    }

    @Override
    public void onSocketDisconnect(SocketAddress socketAddress, boolean isNeedReconnect) {
        // 是否需要重连
        if (!isNeedReconnect) {
            shutDown();
            return;
        }
        reconnect();
    }

    @Override
    public boolean isReconning() {
        return handlerThread != null && handlerThread.isAlive();
    }

}
