package net.northking.cctp.upperComputer.driver.usbmuxd;


import com.dd.plist.NSDictionary;
import net.northking.cctp.upperComputer.driver.usbmuxd.payload.usbmuxd.UsbMuxdPayload;
import net.northking.cctp.upperComputer.driver.usbmuxd.payload.usbmuxd.entity.DeviceConnectionDetail;
import net.northking.cctp.upperComputer.driver.usbmuxd.payload.usbmuxd.response.ListenDeviceResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;

/**
 * 苹果设备变动观察
 */
public class AppleDeviceWatcher extends Thread {

    private Logger logger = LoggerFactory.getLogger(AppleDeviceWatcher.class);

    private static AppleDeviceWatcher instance;

    public static AppleDeviceWatcher getInstance() {
        if (instance == null) {
            instance = new AppleDeviceWatcher();
        }
        return instance;
    }

    private UsbMuxd.ConnectOperator connectOperator;


    /**
     * 设备id序号对应设备唯一id标识符的记录<br>
     * 有些状态下usbmuxd报告的数据中不包含serialNumber
     */
    private static final HashMap<Integer, String> id2SerialNumberMap = new HashMap<>();

    /**
     * 持有的设备变动监听器
     */
    private final ArrayList<OnDeviceChangeListener> listener = new ArrayList<>();

    private AppleDeviceWatcher() {
        setName("AppleDeviceWatcher");
    }

    @SuppressWarnings("BusyWait")
    @Override
    public void run() {
        while (!isInterrupted()) {
            UsbMuxd usbMuxd;
            try {
                usbMuxd = new UsbMuxd();
            } catch (Exception ignore) {
                try {
                    sleep(5000L);
                    continue;
                } catch (InterruptedException e) {
                    break;
                }
            }
            try {
                connectOperator = usbMuxd.startWatchDevice();
            } catch (IOException ignore) {
                try {
                    sleep(5000L);
                    continue;
                } catch (InterruptedException e) {
                    break;
                }
            }

            while (!isInterrupted()) {
                try {
                    NSDictionary readData = UsbMuxdPayload.read(connectOperator.inputStream);
                    ListenDeviceResponse response = new ListenDeviceResponse(readData);
                    DeviceConnectionDetail detail = response.getDetail();
                    if (detail.serialNumber != null) {
                        id2SerialNumberMap.put(detail.deviceId, detail.serialNumber);
                    } else {
                        detail.serialNumber = id2SerialNumberMap.get(detail.deviceId);
                    }
                    if (detail.connectStatus == DeviceConnectionDetail.ConnectStatus.DETACHED) {
                        id2SerialNumberMap.remove(detail.deviceId);
                    }
                    synchronized (listener) {
                        for (OnDeviceChangeListener onDeviceChangeListener : listener) {
                            try {
                                onDeviceChangeListener.onChange(detail);
                            } catch (Exception e) {
                                logger.error("处理设备变化时发生异常", e);
                            }

                        }
                    }
                } catch (Exception ignore) {
                    break;
                }
            }


            try {
                connectOperator.close();
            } catch (Exception ignored) {

            }


        }
    }

    /**
     * 添加一个设备变动监听器
     *
     * @param listener 设备变动监听器
     */
    public void addOnDeviceChangeListener(OnDeviceChangeListener listener) {
        this.listener.add(listener);
    }

    /**
     * 移除一个设备变动监听器<br>
     * 如果原来就不存在，则什么都不会发生
     *
     * @param listener 设备变动监听器
     */
    public void removeOnDeviceChangeListener(OnDeviceChangeListener listener) {
        this.listener.remove(listener);
    }

    public void stopWatch() {
        if (connectOperator != null) {
            try {
                connectOperator.close();
            } catch (Exception e) {
                logger.warn("ios设备监听关闭失败",e);
            }
        }
        interrupt();
    }

    public interface OnDeviceChangeListener {

        void onChange(DeviceConnectionDetail connectionDetail);
    }
}
