package cn.tee3.manager.service;

import android.text.TextUtils;
import android.util.Log;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TimerTask;

import cn.tee3.avd.MScreen;
import cn.tee3.avd.MVideo;
import cn.tee3.avd.NetworkStats;
import cn.tee3.avd.Room;
import cn.tee3.avd.VideoDevice;
import cn.tee3.manager.util.MyTimer;

public class NetworkMonitor {
    private static final int FRAME_THRESHOLD = 0;

    private static HashMap<String, Long> mapNum = new HashMap<>();
    private static HashMap<String, Boolean> mapCheck = new HashMap<>();

    public static boolean setup(Room room, NetworkEventCallback callback) {
        if (!MeetingManager.getInstance().isMeetingInit() || room == null || !room.isWorking() || callback == null) {
            return false;
        }
        MyTimer.cyclePostTask(new TimerTask() {
            @Override
            public void run() {
                if (!MeetingManager.getInstance().isMeetingInit()/* || !room.isWorking()*/) {
                    return;
                }
                List<VideoDevice> deviceList = new ArrayList<>();
                List<MVideo.Camera> cameraList = MeetingManager.getInstance().getMVideo().getSubscribedCameras();
                List<MScreen.ScreenWindow> screenWindowList = MeetingManager.getInstance().getScreen().getSubscribedScreens();
                deviceList.addAll(cameraList);
                for (MScreen.ScreenWindow screenWindow : screenWindowList) {
                    deviceList.add(screenWindow);
                }

                List<NetworkDeviceBean> deviceBeanList = new ArrayList<>();
                Iterator<Map.Entry<String, Long>> iterator = mapNum.entrySet().iterator();
                while (iterator.hasNext()) {
                    boolean isContains = false;
                    Map.Entry<String, Long> next = iterator.next();
                    for (VideoDevice device : deviceList) {
                        if (device.getId().equals(next.getKey())) {
                            isContains = true;
                            break;
                        }
                    }
                    if (!isContains) {
                        iterator.remove();
                    }
                }

                for (VideoDevice device : deviceList) {
                    boolean isChecked = mapCheck.containsKey(device.getId()) ? mapCheck.get(device.getId()) : true;
                    boolean networkCheck = networkCheck(room, device.getId());
                    deviceBeanList.add(new NetworkDeviceBean(device.getId(), mapCheck.get(device.getId()), device instanceof MVideo.Camera));
                }
                if (deviceBeanList.size() > 0 && MeetingManager.getInstance().isMeetingInit()) {
                    callback.networkEvent(deviceBeanList);
                }
            }
        }, 0, 1000);

        return true;
    }

    public static void stop() {
        MyTimer.release();
        mapNum.clear();
        mapCheck.clear();
    }

    private static boolean networkCheck(Room room, String deviceId) {
        NetworkStats.MediaStats stats = room.getMediaStats(deviceId);
        if (stats != null) {
            int bpsSent = stats.getBps_sent() / 1000;           // 上行码流，bps转kbps
            int bpsReceived = stats.getBps_received() / 1000;   // 下行码流，bps转kbps
            int frameRate = stats.getFrame_rate();              // 帧率
            int frameWidth = stats.getFrame_width();            // 视频宽
            int frameHeight = stats.getFrame_height();          // 视频高

            if (!mapNum.containsKey(deviceId)) {
                mapNum.put(deviceId, (long) 0xffffffff);
                Long aLong = mapNum.get(deviceId);
                mapCheck.put(deviceId, true);
            }
            if (bpsReceived == 0 && frameRate > 0) {
                frameRate = 0;
            }

            Long num = mapNum.get(deviceId);
            num = (num << 8) | frameRate;
            mapNum.put(deviceId, num);

            if (isInited(num)) {
                int sum = 0;
                for (int i = 0; i < 4; i++) {
                    sum += (num >> (i * 8)) & 0xff;
                }
                int m = sum / 4;
                mapCheck.put(deviceId, m > FRAME_THRESHOLD);
//                Log.w("qqq", "媒体统计：m = " + m + ", frameRate = " + frameRate + ", userName = " + MeetingManager.getInstance().getMUserManager().getOwnerName(deviceId));
            } else {
                mapCheck.put(deviceId, true);
            }
        }

        return TextUtils.isEmpty(deviceId) ? false : mapCheck.get(deviceId);
    }

    private static boolean isInited(long num) {
        for (int i = 0; i < 4; i++) {
            if ((int) ((num >> (i * 8)) & 0xff) == 0xff) {
                return false;
            }
        }
        return true;
    }

    public static class NetworkDeviceBean {
        private String deviceId;        // 设备id
        private boolean isRunningOk;    // 视频运行正常
        private boolean isCamera;

        public NetworkDeviceBean(String deviceId, boolean isRunningOk, boolean isCamera) {
            this.deviceId = deviceId;
            this.isRunningOk = isRunningOk;
            this.isCamera = isCamera;
        }

        public String getDeviceId() {
            return deviceId;
        }

        public void setDeviceId(String deviceId) {
            this.deviceId = deviceId;
        }

        public boolean isRunningOk() {
            return isRunningOk;
        }

        public void setRunningOk(boolean runningOk) {
            isRunningOk = runningOk;
        }

        public boolean isCamera() {
            return isCamera;
        }

        public void setCamera(boolean camera) {
            isCamera = camera;
        }

        @Override
        public String toString() {
            return "NetworkDeviceBean{" +
                    "deviceId='" + deviceId + '\'' +
                    ", isRunningOk=" + isRunningOk +
                    '}';
        }
    }

    public interface NetworkEventCallback {
        void networkEvent(List<NetworkDeviceBean> deviceBeanList);
    }
}
