#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <stdarg.h>
#include <zipfile/zipfile.h>
#include <sys/types.h>
#include <sys/stat.h>

#include "sysdeps.h"

#define  TRACE_TAG  TRACE_ADB
#include "adb_client.h"

static transport_type __adb_transport = kTransportAny;
static const char* __adb_serial = NULL;

static int __adb_server_port = DEFAULT_ADB_PORT;

void adb_set_transport(transport_type type, const char* serial)
{
    __adb_transport = type;
    __adb_serial = serial;
}

void adb_set_tcp_specifics(int server_port)
{
    __adb_server_port = server_port;
}

int  adb_get_emulator_console_port(void)
{
    const char*   serial = __adb_serial;
    int           port;

    if (serial == NULL) {
        /* if no specific device was specified, we need to look at */
        /* the list of connected devices, and extract an emulator  */
        /* name from it. two emulators is an error                 */
        char*  tmp = adb_query("host:devices");
        char*  p   = tmp;
        if(!tmp) {
            printf("no emulator connected\n");
            return -1;
        }
        while (*p) {
            char*  q = strchr(p, '\n');
            if (q != NULL)
                *q++ = 0;
            else
                q = p + strlen(p);

            if (!memcmp(p, LOCAL_CLIENT_PREFIX, sizeof(LOCAL_CLIENT_PREFIX)-1)) {
                if (serial != NULL) {  /* more than one emulator listed */
                    free(tmp);
                    return -2;
                }
                serial = p;
            }

            p = q;
        }
        free(tmp);

        if (serial == NULL)
            return -1;  /* no emulator found */
    }
    else {
        if (memcmp(serial, LOCAL_CLIENT_PREFIX, sizeof(LOCAL_CLIENT_PREFIX)-1) != 0)
            return -1;  /* not an emulator */
    }

    serial += sizeof(LOCAL_CLIENT_PREFIX)-1;
    port    = strtol(serial, NULL, 10);
    return port;
}

static char __adb_error[256] = { 0 };

const char *adb_error(void)
{
    return __adb_error;
}

static int switch_socket_transport(int fd)
{
    char service[64];
    char tmp[5];
    int len;

    if (__adb_serial)
        snprintf(service, sizeof service, "host:transport:%s", __adb_serial);
    else {
        char* transport_type = "???";

         switch (__adb_transport) {
            case kTransportUsb:
                transport_type = "transport-usb";
                break;
            case kTransportLocal:
                transport_type = "transport-local";
                break;
            case kTransportAny:
                transport_type = "transport-any";
                break;
            case kTransportHost:
                // no switch necessary
                return 0;
                break;
        }

        snprintf(service, sizeof service, "host:%s", transport_type);
    }
    len = strlen(service);
    snprintf(tmp, sizeof tmp, "%04x", len);

    if(writex(fd, tmp, 4) || writex(fd, service, len)) {
        strcpy(__adb_error, "write failure during connection");
        adb_close(fd);
        return -1;
    }
    D("Switch transport in progress\n");

    if(adb_status(fd)) {
        adb_close(fd);
        D("Switch transport failed\n");
        return -1;
    }
    D("Switch transport success\n");
    return 0;
}

int adb_status(int fd)
{
    unsigned char buf[5];
    unsigned len;

    if(readx(fd, buf, 4)) {
        strcpy(__adb_error, "protocol fault (no status)");
        return -1;
    }

    if(!memcmp(buf, "OKAY", 4)) {
        return 0;
    }

    if(memcmp(buf, "FAIL", 4)) {
        sprintf(__adb_error,
                "protocol fault (status %02x %02x %02x %02x?!)",
                buf[0], buf[1], buf[2], buf[3]);
        return -1;
    }

    if(readx(fd, buf, 4)) {
        strcpy(__adb_error, "protocol fault (status len)");
        return -1;
    }
    buf[4] = 0;
    len = strtoul((char*)buf, 0, 16);
    if(len > 255) len = 255;
    if(readx(fd, __adb_error, len)) {
        strcpy(__adb_error, "protocol fault (status read)");
        return -1;
    }
    __adb_error[len] = 0;
    return -1;
}

int _adb_connect(const char *service)
{
    char tmp[5];
    int len;
    int fd;

    D("_adb_connect: %s\n", service);
    len = strlen(service);
    if((len < 1) || (len > 1024)) {
        strcpy(__adb_error, "service name too long");
        return -1;
    }
    snprintf(tmp, sizeof tmp, "%04x", len);

    fd = socket_loopback_client(__adb_server_port, SOCK_STREAM);
    if(fd < 0) {
        strcpy(__adb_error, "cannot connect to daemon");
        return -2;
    }

    if (memcmp(service,"host",4) != 0 && switch_socket_transport(fd)) {
        return -1;
    }

    if(writex(fd, tmp, 4) || writex(fd, service, len)) {
        strcpy(__adb_error, "write failure during connection");
        adb_close(fd);
        return -1;
    }

    if(adb_status(fd)) {
        adb_close(fd);
        return -1;
    }

    D("_adb_connect: return fd %d\n", fd);
    return fd;
}

int adb_connect(const char *service)
{
    // first query the adb server's version
    int fd = _adb_connect("host:version");

    D("adb_connect: service %s\n", service);
    if(fd == -2) {
        fprintf(stdout,"* daemon not running. starting it now on port %d *\n",
                __adb_server_port);
    start_server:
        if(launch_server(__adb_server_port)) {
            fprintf(stderr,"* failed to start daemon *\n");
            return -1;
        } else {
            fprintf(stdout,"* daemon started successfully *\n");
        }
        /* give the server some time to start properly and detect devices */
        adb_sleep_ms(3000);
        // fall through to _adb_connect
    } else {
        // if server was running, check its version to make sure it is not out of date
        char buf[100];
        int n;
        int version = ADB_SERVER_VERSION - 1;

        // if we have a file descriptor, then parse version result
        if(fd >= 0) {
            if(readx(fd, buf, 4)) goto error;

            buf[4] = 0;
            n = strtoul(buf, 0, 16);
            if(n > (int)sizeof(buf)) goto error;
            if(readx(fd, buf, n)) goto error;
            adb_close(fd);

            if (sscanf(buf, "%04x", &version) != 1) goto error;
        } else {
            // if fd is -1, then check for "unknown host service",
            // which would indicate a version of adb that does not support the version command
            if (strcmp(__adb_error, "unknown host service") != 0)
                return fd;
        }

        if(version != ADB_SERVER_VERSION) {
            printf("adb server is out of date.  killing...\n");
            fd = _adb_connect("host:kill");
            adb_close(fd);

            /* XXX can we better detect its death? */
            adb_sleep_ms(2000);
            goto start_server;
        }
    }

    // if the command is start-server, we are done.
    if (!strcmp(service, "host:start-server"))
        return 0;

    fd = _adb_connect(service);
    if(fd == -2) {
        fprintf(stderr,"** daemon still not running");
    }
    D("adb_connect: return fd %d\n", fd);

    return fd;
error:
    adb_close(fd);
    return -1;
}


int adb_command(const char *service)
{
    int fd = adb_connect(service);
    if(fd < 0) {
        return -1;
    }

    if(adb_status(fd)) {
        adb_close(fd);
        return -1;
    }

    return 0;
}

char *adb_query(const char *service)
{
    char buf[5];
    unsigned n;
    char *tmp;

    D("adb_query: %s\n", service);
    int fd = adb_connect(service);
    if(fd < 0) {
        fprintf(stderr,"error: %s\n", __adb_error);
        return 0;
    }

    if(readx(fd, buf, 4)) goto oops;

    buf[4] = 0;
    n = strtoul(buf, 0, 16);
    if(n > 1024) goto oops;

    tmp = malloc(n + 1);
    if(tmp == 0) goto oops;

    if(readx(fd, tmp, n) == 0) {
        tmp[n] = 0;
        adb_close(fd);
        return tmp;
    }
    free(tmp);

oops:
    adb_close(fd);
    return 0;
}
