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

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.payload.Payload;
import org.xml.sax.SAXException;

import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;

public abstract class UsbMuxdPayload extends Payload {

    /**
     * body内容的长度数据字节长度
     */
    private static final int BODY_LENGTH_BYTE_SIZE = 16;

    /**
     * 将数据写入对usbmuxd的流
     *
     * @param outputStream 通过OutputStream将数据传输给usbmuxd
     * @throws IOException 发生输入/输出错误
     */
    public final void write(OutputStream outputStream) throws IOException {
        byte[] bodyBytes = toData().toXMLPropertyList().getBytes(StandardCharsets.UTF_8);
        int len = BODY_LENGTH_BYTE_SIZE + bodyBytes.length;
        int version = 1;
        int request = 8;
        int tag = 1;
        ByteBuffer buffer = ByteBuffer.allocate(len);
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        buffer.putInt(0, len);
        buffer.putInt(4, version);
        buffer.putInt(8, request);
        buffer.putInt(12, tag);
        int i = 16;
        for (Byte b : bodyBytes) {//031603
            buffer.put(i++, b);
        }
        outputStream.write(buffer.array());
        outputStream.flush();
    }

    /**
     * 读取来自usbmuxd的数据流为NSDictionary
     *
     * @param inputStream 要读取的流
     * @return 解析为NSDictionary类型的数据
     * @throws IOException                  发生输入输出错误
     * @throws PropertyListFormatException  转换格式时错误
     * @throws ParseException               转换错误
     * @throws ParserConfigurationException 转换器配置错误
     * @throws SAXException                 xml错误
     */
    public static NSDictionary read(InputStream inputStream) throws IOException, PropertyListFormatException, ParseException, ParserConfigurationException, SAXException {
        byte[] sizeBytes = new byte[BODY_LENGTH_BYTE_SIZE];
        int readSizeBytesCount = inputStream.read(sizeBytes);
        if (readSizeBytesCount != BODY_LENGTH_BYTE_SIZE) {
            throw new IOException("读取body长度数据时读取不到足够的数据，需要16个字节，实际读取到" + readSizeBytesCount);
        }
        ByteBuffer bodyLengthDecodeBuffer = ByteBuffer.allocate(BODY_LENGTH_BYTE_SIZE);
        bodyLengthDecodeBuffer.order(ByteOrder.LITTLE_ENDIAN);
        bodyLengthDecodeBuffer.put(sizeBytes);
        int bodySize = bodyLengthDecodeBuffer.getInt(0);
        if (bodySize == 0) {
            return new NSDictionary();
        }

        byte[] bodyBytes = new byte[bodySize - BODY_LENGTH_BYTE_SIZE];
        int readBodyBytesCount = inputStream.read(bodyBytes);
        if (readBodyBytesCount != bodyBytes.length) {
            throw new IOException("读取body时数据不足，需要" + bodyBytes.length + "字节，实际读取到" + readBodyBytesCount + "字节");
        }
        NSObject resultObject = PropertyListParser.parse(bodyBytes);

        return (NSDictionary) resultObject;
    }
}
