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


import net.northking.cctp.upperComputer.driver.ios.command.data.*;
import net.northking.cctp.upperComputer.driver.ios.command.listener.AppBatteryDataListener;
import net.northking.cctp.upperComputer.driver.ios.command.listener.ScreenInfoDataListener;
import net.northking.cctp.upperComputer.driver.ios.packet.*;
import net.northking.cctp.upperComputer.driver.usbmuxd.AppleDevice;
import net.northking.cctp.upperComputer.driver.usbmuxd.UsbMuxd;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

public final class NKAgent {

    private final static Logger logger = LoggerFactory.getLogger(NKAgent.class);

    public static final int PORT = 50001;

    private final DeviceSocketProvider deviceSocketProvider;

    private PacketTransfer packetTransfer;

    private final ArrayList<OnAppBatteryDataListener> onAppBatteryDataListeners = new ArrayList<>();

    private final ArrayList<OnScreenInfoDataListener> onScreenInfoDataListeners = new ArrayList<>();

    private Runnable onDisconnectListener = null;

    public NKAgent(AppleDevice appleDevice) {
        this(new UsbMuxd(), appleDevice);
    }

    public NKAgent(UsbMuxd usbMuxd, AppleDevice appleDevice) {
        this(new LocalUsbmuxdDeviceSocketProvider(usbMuxd, appleDevice, PORT));
    }
    public NKAgent(DeviceSocketProvider deviceSocketProvider) {
        this.deviceSocketProvider = deviceSocketProvider;
    }

    public String getUUID() {
        return deviceSocketProvider.getUdid();
    }

    public void connect() throws IOException {
        logger.debug("开始连接设备【{}】的nkAgent........",getUUID());
        initTransfer();
        initAsyncListener();
        logger.debug("设备【{}】连接结果：{}........",getUUID(),packetTransfer.isConnected());
    }


    public void setOnDisconnectListener(Runnable listener) {
        this.onDisconnectListener = listener;
        if (packetTransfer != null) {
            packetTransfer.setOnDisconnectListener(listener);
        }
    }

    private void initTransfer() throws IOException {
        DeviceSocketStream deviceSocketStream = deviceSocketProvider.createConnect();
        packetTransfer = new PacketTransfer(deviceSocketStream.getInputStream(), deviceSocketStream.getOutputStream(), deviceSocketProvider.getUdid());
        if (this.onDisconnectListener != null) {
            packetTransfer.setOnDisconnectListener(this.onDisconnectListener);
        }
    }

    private void initAsyncListener() {
        if (packetTransfer == null) throw new RuntimeException("先调用initTransfer再初始化异步监听");
        packetTransfer.addAsyncListener(new AppBatteryDataListener() {
            @Override
            public void handle(PacketTransfer transfer, ICommandPacket packet) {
                super.handle(transfer, packet);
                ArrayList<OnAppBatteryDataListener> listeners = new ArrayList<OnAppBatteryDataListener>(onAppBatteryDataListeners.size());
                synchronized (onAppBatteryDataListeners) {
                    listeners.addAll(onAppBatteryDataListeners);
                }
                for (OnAppBatteryDataListener l : listeners) {
                    l.onAppBatteryData(getAppBatteryData());
                }
            }
        });
        packetTransfer.addAsyncListener(new ScreenInfoDataListener() {
            @Override
            public void handle(PacketTransfer transfer, ICommandPacket packet) {
                super.handle(transfer, packet);
                ArrayList<OnScreenInfoDataListener> listeners = new ArrayList<OnScreenInfoDataListener>(onScreenInfoDataListeners.size());
                synchronized (onScreenInfoDataListeners) {
                    listeners.addAll(onScreenInfoDataListeners);
                }
                for (OnScreenInfoDataListener l : listeners) {
                    l.onScreenInfoData(getScreenInfoData());
                }
            }
        });
    }

    public void addOnAppBatteryDataListener(OnAppBatteryDataListener listener) {
        synchronized (onAppBatteryDataListeners) {
            onAppBatteryDataListeners.add(listener);
        }
    }

    public void removeOnAppBatteryDataListener(OnAppBatteryDataListener listener) {
        synchronized (onAppBatteryDataListeners) {
            onAppBatteryDataListeners.remove(listener);
        }
    }

    public void addOnScreenInfoDataListener(OnScreenInfoDataListener listener) {
        synchronized (onScreenInfoDataListeners) {
            onScreenInfoDataListeners.add(listener);
        }
    }

    public void removeOnScreenInfoDataListener(OnScreenInfoDataListener listener) {
        synchronized (onScreenInfoDataListeners) {
            onScreenInfoDataListeners.remove(listener);
        }
    }

    public ScreenInfoData screenInfo() {
        ICommandPacket packet = packetTransfer.syncSend(2);
        if (packet == null) return null;
        ScreenInfoData screenInfo = new ScreenInfoData();
        packet.fillICommandData(screenInfo);
        return screenInfo;
    }

    public TextCommandData uiTreeJson() {
        ICommandPacket packet = packetTransfer.syncSend(3);
        if (packet == null) return null;
        TextCommandData stringCommandData = new TextCommandData();
        packet.fillICommandData(stringCommandData);
        return stringCommandData;
    }

    public UiNodeData uiTreeNode() {
        ICommandPacket packet = packetTransfer.syncSend(4);
        if (packet == null) return null;
        UiNodeData node = new UiNodeData();
        packet.fillICommandData(node);
        return node;
    }

    public UiNodeData uiNodeInfo(SearchUiNodeData searchUiNodeData) {
        ICommandPacket packet = packetTransfer.syncSend(26, searchUiNodeData);
        if (packet == null) return null;
        UiNodeData node = new UiNodeData();
        packet.fillICommandData(node);
        return node;
    }

    /**
     * 设置屏幕方向
     * @param aByte 取值范围：[1, 4]
     * @return 是否设置成功
     */
    public boolean setScreenOrientation(Byte aByte) {
        if (aByte < 1 || aByte > 4) {
            throw new IllegalArgumentException("参数范围错误");
        }
        ByteCommandData data = new ByteCommandData();
        data.aByte = aByte;
        ICommandPacket packet = packetTransfer.syncSend(3, data);
        BooleanCommandData bool = new BooleanCommandData();
        packet.fillICommandData(bool);
        return bool.isSuccess();
    }

    public boolean clickUiNode(SearchUiNodeData searchUiNodeData,int commandId) {
        ICommandPacket packet = packetTransfer.syncSend(commandId, searchUiNodeData);
        if (packet == null) return false;
        BooleanCommandData bool = new BooleanCommandData();
        packet.fillICommandData(bool);
        return bool.isSuccess();
    }

    public boolean handleTextUiNode(ICommandData data, int commandId) {
        ICommandPacket packet = packetTransfer.syncSend(commandId, data);
        if (packet == null) return false;
        BooleanCommandData bool = new BooleanCommandData();
        packet.fillICommandData(bool);
        return bool.isSuccess();
    }

    public boolean handleDeleteTextUiNode(int commandId) {
        ICommandPacket packet = packetTransfer.syncSend(commandId);
        if (packet == null) return false;
        BooleanCommandData bool = new BooleanCommandData();
        packet.fillICommandData(bool);
        return bool.isSuccess();
    }


    public boolean handleClearTextUiNode(ICommandData data, int commandId) {
//        System.out.println('删除');
        ICommandPacket packet = packetTransfer.syncSend(commandId, data);
        if (packet == null) return false;
        BooleanCommandData bool = new BooleanCommandData();
        packet.fillICommandData(bool);
        return bool.isSuccess();
    }

    /*
   设置JPEGServer的帧率
   rate 取值[0, 15]
    */
    public boolean setMJPEGServerRate(int rate) {
        if (rate < 0 || rate > 60) {
            throw new IllegalArgumentException("参数范围错误");
        }
        IntCommandData data = new IntCommandData();
        data.anInt = rate;
        ICommandPacket packet = packetTransfer.syncSend(28, data);
        if (packet == null) return false;
        BooleanCommandData bool = new BooleanCommandData();
        packet.fillICommandData(bool);
        return bool.isSuccess();
    }


    public  boolean drawLine(String string) {
        TextData data = new TextData();
        data.setText(string);
        ICommandPacket packet = packetTransfer.syncSend(29, data);
        if (packet == null) return false;
        BooleanCommandData bool = new BooleanCommandData();
        packet.fillICommandData(bool);
        return bool.isSuccess();
    }

    public String activeAppBundleId() {
        ICommandPacket packet = packetTransfer.syncSend(30);
        TextData data = new TextData();
        packet.fillICommandData(data);
        return data.text;
    }

    /*
    停止所有推图流
     */
    public  boolean disconnectAllMJpegSever() {
        ICommandPacket packet = packetTransfer.syncSend(31);
        if (packet == null) return false;
        BooleanCommandData bool = new BooleanCommandData();
        packet.fillICommandData(bool);
        return bool.isSuccess();
    }

    /**
     * 启动app
     * @param string bundleId
     * @return 是否设置成功
     */
    public boolean launchApp(String string) {
        if (string.isEmpty()) {
            throw new IllegalArgumentException("bundleId不能为空");
        }
        TextData data = new TextData();
        data.setText(string);
        ICommandPacket packet = packetTransfer.syncSend(32, data);
        if (packet == null) return false;
        BooleanCommandData bool = new BooleanCommandData();
        packet.fillICommandData(bool);
        return bool.isSuccess();
    }

    public ScreenShotData screenShot() {
        ICommandPacket packet = packetTransfer.syncSend(33);
        if (packet == null) return null;
        ScreenShotData screenShotData = new ScreenShotData();
        packet.fillICommandData(screenShotData);
        return screenShotData;
    }

    /**
     * 杀死app
     * @param string bundleId
     * @return 是否成功
     */
    public boolean terminateApp(String string) {
        if (string.isEmpty()) {
            throw new IllegalArgumentException("bundleId不能为空");
        }
        TextData data = new TextData();
        data.setText(string);
        ICommandPacket packet = packetTransfer.syncSend(34, data);
        if (packet == null) return false;
        BooleanCommandData bool = new BooleanCommandData();
        packet.fillICommandData(bool);
        return bool.isSuccess();
    }


    public boolean getStatus() {
        return this.packetTransfer.isConnected();
    }
//
//    public boolean clickUiNode(SearchUiNodeData.SearchChain chain) {
//        return clickUiNode(chain.toSearchString(null));
//    }
//
//    public boolean clickUiNode(String searchChainText) {
//        var sendData = new TextCommandData();
//        sendData.setText(searchChainText);
//        var packet = packetTransfer.syncSend(6, sendData);
//        var bool = new BooleanCommandData();
//        packet.fillICommandData(bool);
//        return bool.isSuccess();
//    }

    public interface OnAppBatteryDataListener {
        void onAppBatteryData(AppBatteryData appBatteryData);
    }

    public interface OnScreenInfoDataListener {
        void onScreenInfoData(ScreenInfoData screenInfoData);
    }


}
