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

import com.dd.plist.NSDictionary;
import com.dd.plist.NSObject;
import com.dd.plist.PropertyListFormatException;
import com.dd.plist.PropertyListParser;
import net.northking.cctp.upperComputer.driver.usbmuxd.AppleDevice;
import net.northking.cctp.upperComputer.driver.usbmuxd.UsbMuxd;
import net.northking.cctp.upperComputer.driver.usbmuxd.payload.service.ServicePayload;
import net.northking.cctp.upperComputer.driver.usbmuxd.payload.service.request.QueryTypeRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;

import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.text.ParseException;

public abstract class AppleDeviceInnerService {

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

    UsbMuxd.ConnectOperator connectOperator = null;
    final UsbMuxd usbMuxd;
    final AppleDevice appleDevice;

    protected AppleDeviceInnerService(UsbMuxd usbMuxd, AppleDevice appleDevice) {
        this.usbMuxd = usbMuxd;
        this.appleDevice = appleDevice;
    }


    /**
     * 服务在设备内部监听的端口号
     *
     * @return 端口号
     */
    abstract int getPort();

    public String getServiceName() {
        try {
            QueryTypeRequest queryTypeRequest = new QueryTypeRequest();
            write(queryTypeRequest);
            NSDictionary result = read();
            NSObject typeObject = result.get("Type");
            if (typeObject != null) {
                return typeObject.toJavaObject(String.class);
            }
        } catch (IOException e) {
            logger.error("获得设备内部服务名称时发生IO异常", e);
        }
        return null;
    }

    synchronized void write(ServicePayload payload) throws IOException {
        if (connectOperator == null) throw new IllegalStateException("connectOperator 为 null，可能未初始化或已关闭");

        byte[] bytes = (payload.toData().toXMLPropertyList() + "\n").getBytes();
        int len = bytes.length;
        ByteBuffer buffer = ByteBuffer.allocate(4 + len);
        buffer.putInt(len);
        buffer.put(bytes);
        connectOperator.outputStream.write(buffer.array());
    }

    synchronized NSDictionary read() throws IOException {
        if (connectOperator == null) throw new IllegalStateException("connectOperator 为 null，可能未初始化或已关闭");

        byte[] header = new byte[4];
        if (connectOperator.inputStream.read(header) != 4) {
            return new NSDictionary();
        }
        ByteBuffer buffer = ByteBuffer.allocate(4);
        buffer.put(header);
        buffer.position(0);
        int bodySize = buffer.getInt();
        if (bodySize == 0) {
            return new NSDictionary();
        }
        byte[] byteArray = new byte[bodySize];
        if (connectOperator.inputStream.read(byteArray) != bodySize) {
            return new NSDictionary();
        }
        try {
            NSObject nsObject = PropertyListParser.parse(byteArray);
            return (NSDictionary) nsObject;
        } catch (PropertyListFormatException | ParseException | ParserConfigurationException | SAXException e) {
            logger.warn("NSObject解析出错：" + new String(byteArray));
            return null;
        }
    }

    public void close() {
        if (connectOperator != null) {
            try {
                connectOperator.socket.close();
            } catch (IOException e) {
                logger.warn("关闭usbmuxd的socket时发生IO异常", e);
            }
            connectOperator = null;
        }
    }


}
