package com.jld.vod.socket;

import android.content.Context;
import android.util.Log;


import com.jld.vod.config.Config;
import com.jld.vod.interfaces.OnMessageReceiveListener;
import com.jld.vod.model.event.ReceiveEvent;

import org.greenrobot.eventbus.EventBus;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class ReceiveUDPSocket {

    private static final String TAG = "UDPSocket";

    private static final int BUFFER_LENGTH = 1024;
    private byte[] receiveByte = new byte[BUFFER_LENGTH];

    private static String BROADCAST_IP = "192.168.43.255";

    // 端口号，飞鸽协议默认端口2425
    public static final int CLIENT_PORT = 2425;

    private boolean isThreadRunning = false;

    private Context mContext;
    private DatagramSocket client;
    private DatagramPacket receivePacket;

    private long lastReceiveTime = 0;
    private static final long TIME_OUT = 120 * 1000;
    private static final long HEARTBEAT_MESSAGE_DURATION = 5 * 1000;

    private ExecutorService mThreadPool;
    private Thread clientThread;

    private final List<OnMessageReceiveListener> messageReceiveList;

    public ReceiveUDPSocket(Context context) {

        this.mContext = context;

        int cpuNumbers = Runtime.getRuntime().availableProcessors();
        // 根据CPU数目初始化线程池
        mThreadPool = Executors.newFixedThreadPool(cpuNumbers * Config.POOL_SIZE);
        // 记录创建对象时的时间
        lastReceiveTime = System.currentTimeMillis();

        messageReceiveList = new ArrayList<>();

        Log.d(TAG, "创建 UDP 对象");
//        createUser();
    }

    public void addOnMessageReceiveListener(OnMessageReceiveListener listener) {
        messageReceiveList.add(listener);
    }


    public void startUDPSocket() {
        if (client != null) return;
        try {
            // 表明这个 Socket 在设置的端口上监听数据。
            client = new DatagramSocket(CLIENT_PORT);
            client.setReuseAddress(true);
            if (receivePacket == null) {
                // 创建接受数据的 packet
                receivePacket = new DatagramPacket(receiveByte, BUFFER_LENGTH);
            }

            startSocketThread();
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }

    /**
     * 开启接收数据的线程
     */
    private void startSocketThread() {
        clientThread = new Thread(new Runnable() {
            @Override
            public void run() {
                receiveMessage();
            }
        });
        isThreadRunning = true;
        clientThread.start();
        Log.d(TAG, "开启 UDP 数据接收线程");
    }

    /**
     * 处理接受到的消息
     */
    private void receiveMessage() {
        while (isThreadRunning) {
            try {
                if (client != null && receivePacket != null) {
                    client.receive(receivePacket);
                }
                lastReceiveTime = System.currentTimeMillis();
                Log.d(TAG, "receive packet success...");
            } catch (IOException e) {
                Log.e(TAG, "UDP数据包接收失败！线程停止");
                stopUDPSocket();
                e.printStackTrace();
                return;
            }

            if (receivePacket == null || receivePacket.getLength() == 0) {
                Log.e(TAG, "无法接收UDP数据或者接收到的UDP数据为空");
                continue;
            }

            String strReceive = new String(receivePacket.getData(), receivePacket.getOffset(), receivePacket.getLength());
            Log.d(TAG, strReceive + " from " + receivePacket.getAddress().getHostAddress() + ":" + receivePacket.getPort());

            EventBus.getDefault().post(new ReceiveEvent(strReceive));
            //解析接收到的 json 信息
            //notifyMessageReceive(strReceive);
            // 每次接收完UDP数据后，重置长度。否则可能会导致下次收到数据包被截断。
            if (receivePacket != null) {
                receivePacket.setLength(BUFFER_LENGTH);
            }
        }
    }

    /**
     * 将消息通过接口发送到每个页面
     *
     * @param strReceive
     */
    private void notifyMessageReceive(String strReceive) {
        for (OnMessageReceiveListener listener : messageReceiveList) {
            if (listener != null) {
                listener.onMessageReceived(strReceive);
            }
        }
    }

    public void stopUDPSocket() {
        isThreadRunning = false;
        receivePacket = null;
        if (clientThread != null) {
            clientThread.interrupt();
        }
        if (mThreadPool != null) {
            mThreadPool.shutdown();
        }
        if (client != null) {
            client.close();
            client = null;
        }

    }

}
