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

import net.northking.cctp.upperComputer.driver.adb.Adb;
import net.northking.cctp.upperComputer.driver.adb.AdbDevice;
import net.northking.cctp.upperComputer.driver.adb.AdbTransport;

import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;

public class StandaloneCommandRunner {

    /**
     * 状态正常，输出指令应该输出的数据
     */
    private static final int STATUS_CODE_OK = 0;
    /**
     * 执行超时，不附带任何数据
     */
    private static final int STATUS_CODE_TIMEOUT = -1;
    /**
     * 执行时发生异常，输出异常堆栈文本
     */
    private static final int STATUS_CODE_EXCEPTION = -2;

    private final Adb adb;
    private final AdbDevice adbDevice;
    private final String className;
    private String args = "";


    public StandaloneCommandRunner(Adb adb, AdbDevice adbDevice, String className, String args) {
        this.className = className;
        this.adb = adb;
        this.adbDevice = adbDevice;
        this.args = args;
    }

    public byte[] run() throws StandaloneCommandException, StandaloneCommandTimeoutException, IOException {
        try (AdbTransport transport = adb.shell(adbDevice, "export CLASSPATH=/data/local/tmp/agent.apk;app_process /system/bin " + className + " " + args)) {
            DataInputStream dataInput = getDataInputStream(transport);
            int status = dataInput.readInt();
            switch (status) {
                case STATUS_CODE_OK:
                    int dataLength = dataInput.readInt();
                    byte[] data = new byte[dataLength];
                    dataInput.readFully(data);
                    return data;
                case STATUS_CODE_TIMEOUT:
                    throw new StandaloneCommandTimeoutException("Agent独立指令：class:" + className + " args:" + args + " 超时");
                case STATUS_CODE_EXCEPTION:
                    dataLength = dataInput.readInt();
                    data = new byte[dataLength];
                    dataInput.readFully(data);
                    throw new StandaloneCommandException(new String(data));
                default:
                    throw new IOException("Agent独立指令：class:" + className + " args:" + args + " 未知状态码：" + status);
            }
        }
    }

    private DataInputStream getDataInputStream(AdbTransport transport) throws IOException {
        if (transport == null) {
            throw new IOException("无法创建Shell");
        }
        InputStream inputStream = transport.getInputStream();
        int bannerCount = 0;
        while (bannerCount < 5) {
            int b = inputStream.read();
            if (b == -1) {
                throw new EOFException("Agent独立指令：class:" + className + " args:" + args + " 未能读取到banner");
            }
            if (b == (byte) 0x01) {
                bannerCount++;
            } else {
                bannerCount = 0;
            }
        }
        return new DataInputStream(inputStream);
    }


}
