// Copyright 2014 The Android Open Source Project
//
// This software is licensed under the terms of the GNU General Public
// License version 2, as published by the Free Software Foundation, and
// may be copied, distributed, and modified under those terms.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

#include "android/wear-agent/PairUpWearPhone.h"


#include "android/base/async/AsyncReader.h"
#include "android/base/async/AsyncStatus.h"
#include "android/base/async/AsyncWriter.h"
#include "android/base/async/Looper.h"
#include "android/base/containers/StringVector.h"
#include <android/base/Limits.h>
#include "android/base/Log.h"
#include "android/base/memory/ScopedPtr.h"
#include "android/base/sockets/SocketErrors.h"
#include "android/base/sockets/SocketUtils.h"
#include "android/base/String.h"
#include "android/utils/debug.h"

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define  DPRINT(...)  do {  if (VERBOSE_CHECK(adb)) dprintn(__VA_ARGS__); } while (0)

namespace android {
namespace wear {

using namespace ::android::base;

typedef ScopedPtr<Looper::FdWatch> FdWatch;
typedef ScopedPtr<Looper::Timer> Timer;

class PairUpWearPhoneImpl {
public:
    PairUpWearPhoneImpl(Looper* looper,
                        const StringVector& devices,
                        int adbHostPort);

    ~PairUpWearPhoneImpl();

    void writeAdbServerSocket();
    void readAdbServerSocket();

    void writeEmulatorConsoleSocket();
    void readEmulatorConsoleSocket();

    bool isDone() const;
    void cleanUp();

private:
    typedef StringVector StrQueue;
    enum CommunicationState {

         PAIRUP_ERROR = 0,

         // when ask adb for device property, need to first ask adb to setup transfer,
         // wait for "OKAY" from adb, then send the query command(which is transferred
         // by adb to the device), and read reply from adb until adb disconnect

         // get product name to distinguish wear from phone
         TO_GET_PRODUCT_NAME_INIT_XFER,
         TO_GET_PRODUCT_NAME_WAIT_OKAY,
         TO_GET_PRODUCT_NAME_SEND_CMD,
         TO_GET_PRODUCT_NAME_READ_REPLY,

         // find out if the phone has wearable app, which is responsible for communication
         // with wear
         TO_GET_WEARABLE_APP_INIT_XFER,
         TO_GET_WEARABLE_APP_WAIT_OKAY,
         TO_GET_WEARABLE_APP_SEND_CMD,
         TO_GET_WEARABLE_APP_READ_REPLY,

         // perform ip forwarding on real device
         // "host-serial:phone-serial-number:forward:tcp:5601;5601"
         TO_FORWARD_IP_SEND_CMD,
         TO_FORWARD_IP_WAIT_OKAY,

         // perform ip redirection on emulator
         // the above command does not work on emulator, so we have to connect to the emulator
         // console and issue command "redir add"
         TO_READ_GREETINGS_FROM_CONSOLE,
         TO_SEND_REDIR_CMD_TO_CONSOLE,

         PAIRUP_SUCCESS,

         PAIRUP_ALREADY_CLEANEDUP
    };
    enum MessageType {
         TRANSFER = 1,
         FORWARDIP,
         PROPERTY,
         WEARABLE_APP_PKG
    };
    static const int READ_BUFFER_SIZE  = 1024;
    static const int WRITE_BUFFER_SIZE = 1024;

    Looper* mLooper;

    // member related to adb host
    int mAdbHostPort;
    FdWatch mAdbWatch;

    // member related to emulator console
    int mConsolePort;
    FdWatch mConsoleWatch;

    // device categories
    String mDeviceInProbing;
    StrQueue mUnprobedDevices;
    StrQueue mWearDevices;
    StrQueue mPhoneDevices;

    CommunicationState mState;

    // asynchronous reader and writer
    AsyncReader mAsyncReader;
    AsyncWriter mAsyncWriter;
    char* mReadBuffer;
    char* mWriteBuffer;
    String mReply;

    // whenever device list changes, call the following
    void updateDevices(const StringVector& devices);
    void startProbeNextDevice();

    // socket connection methods
    bool openConnection(int port,
                        FdWatch* watch,
                        Looper::FdWatch::Callback callback);

    void closeConnection(FdWatch* watch);
    void openAdbConnection();
    void openConsoleConnection();

    // read and write mode handling methods
    void switchToRead(FdWatch* watch) {
        (*watch)->wantRead();
        (*watch)->dontWantWrite();
    }

    void switchToWrite(FdWatch* watch) {
        (*watch)->wantWrite();
        (*watch)->dontWantRead();
    }

    // connect wear to phone by setuping port forwarding on emulator or real device
    bool checkForWearDevice();
    bool checkForCompatiblePhone();
    void startConnectWearAndPhone();

    bool startReadConsole();

    // adb asynchronous read/write methods: all return true on success
    // false if need to try again or on error. When error happens,
    // will call startProbeNextDevice
    bool startWriteCommandToAdb(int queryType, const char* message);
    bool completeWriteCommandToAdb();
    bool startReadHeaderFromAdb();
    bool completeReadHeaderFromAdb();
    bool completeReadAllDataFromAdb();
};

static const char kWearableAppName[] = "com.google.android.wearable";

// callback that talks to adb server on the host computer
static void _on_adb_server_socket_fd(void* opaque, int fd, unsigned events) {
    PairUpWearPhoneImpl * pairup = static_cast<PairUpWearPhoneImpl*>(opaque);
    if (!pairup) return;

    if (events & Looper::FdWatch::kEventRead) {
        pairup->readAdbServerSocket();
    } else if (events & Looper::FdWatch::kEventWrite) {
        pairup->writeAdbServerSocket();
    }
    if (pairup->isDone()) {
        pairup->cleanUp();
    }
}

// callback that talks to emulator console
static void _on_emulator_console_socket_fd(void* opaque, int fd, unsigned events) {
    PairUpWearPhoneImpl * pairup = static_cast<PairUpWearPhoneImpl*>(opaque);
    if (!pairup) return;

    if (events & Looper::FdWatch::kEventRead) {
        pairup->readEmulatorConsoleSocket();
    } else if (events & Looper::FdWatch::kEventWrite) {
        pairup->writeEmulatorConsoleSocket();
    }
    if (pairup->isDone()) {
        pairup->cleanUp();
    }
}

//-------------- callbacks for IO with adb server and emulator console
void PairUpWearPhoneImpl::readAdbServerSocket() {

    switch(mState) {
        case TO_GET_PRODUCT_NAME_WAIT_OKAY:
            if (!completeReadHeaderFromAdb()) return;
            if (!startWriteCommandToAdb(PROPERTY, "ro.product.name")) return;
            mState = TO_GET_PRODUCT_NAME_SEND_CMD;
            return;

        case TO_GET_PRODUCT_NAME_READ_REPLY:
            if (!completeReadAllDataFromAdb()) return;
            if (checkForWearDevice()) {
                startConnectWearAndPhone();
                return;
            }
            if (!startWriteCommandToAdb(TRANSFER, mDeviceInProbing.c_str())) return;
            mState = TO_GET_WEARABLE_APP_INIT_XFER;
            return;

        case TO_GET_WEARABLE_APP_WAIT_OKAY:
            if (!completeReadHeaderFromAdb()) return;
            if (!startWriteCommandToAdb(WEARABLE_APP_PKG, kWearableAppName)) return;
            mState = TO_GET_WEARABLE_APP_SEND_CMD;
            return;

        case TO_GET_WEARABLE_APP_READ_REPLY:
            if (!completeReadAllDataFromAdb()) return;
            if (checkForCompatiblePhone()) {
                startConnectWearAndPhone();
                return;
            }
            startProbeNextDevice();
            return;

        case TO_FORWARD_IP_WAIT_OKAY:
            if (!completeReadHeaderFromAdb()) return;
            mState = PAIRUP_SUCCESS;
            return;

        default:
            startProbeNextDevice();
            return;
    }
}

void PairUpWearPhoneImpl::writeAdbServerSocket() {

    switch (mState) {
        case TO_GET_PRODUCT_NAME_INIT_XFER:
            if (!completeWriteCommandToAdb()) return;
            if (!startReadHeaderFromAdb()) return;
            mState = TO_GET_PRODUCT_NAME_WAIT_OKAY;
            return;

        case TO_GET_PRODUCT_NAME_SEND_CMD:
            if (!completeWriteCommandToAdb()) return;
            mState = TO_GET_PRODUCT_NAME_READ_REPLY;
            mReply.clear();
            switchToRead(&mAdbWatch);
            return;

        case TO_GET_WEARABLE_APP_INIT_XFER:
            if (!completeWriteCommandToAdb()) return;
            if (!startReadHeaderFromAdb()) return;
            mState = TO_GET_WEARABLE_APP_WAIT_OKAY;
            return;

        case TO_GET_WEARABLE_APP_SEND_CMD:
            if (!completeWriteCommandToAdb()) return;
            mState = TO_GET_WEARABLE_APP_READ_REPLY;
            mReply.clear();
            switchToRead(&mAdbWatch);
            return;

        case TO_FORWARD_IP_SEND_CMD:
            if (!completeWriteCommandToAdb()) return;
            if (!startReadHeaderFromAdb()) return;
            mState = TO_FORWARD_IP_WAIT_OKAY;
            return;

        default:
            startProbeNextDevice();
            return;
    }

}

void PairUpWearPhoneImpl::readEmulatorConsoleSocket() {
    const ssize_t size = socketRecv(mConsoleWatch->fd(),
                                    mReadBuffer,
                                    READ_BUFFER_SIZE);
    if (size > 0) {
        mReply.append(mReadBuffer, size);
        DPRINT("read console message: %s\n", mReply.c_str());
        if (mReply.contains("OK")) {
            DPRINT("received mesg from console:\n%s\n", mReply.c_str());
            snprintf(mWriteBuffer, WRITE_BUFFER_SIZE, "redir add tcp:5601:5601\nquit\n");
            DPRINT("sending query to console:\n%s", mWriteBuffer);
            mAsyncWriter.reset(mWriteBuffer,
                               ::strlen(mWriteBuffer),
                               mConsoleWatch.get());
            switchToWrite(&mConsoleWatch);
            mState = TO_SEND_REDIR_CMD_TO_CONSOLE;
        }
    } else {
        DPRINT("error happened when reading console\n");
        startProbeNextDevice();
    }
}

void PairUpWearPhoneImpl::writeEmulatorConsoleSocket() {
    const AsyncStatus status = mAsyncWriter.run();

    if (status == kAsyncCompleted) {
        mState = PAIRUP_SUCCESS;
    } else if (status == kAsyncError) {
        DPRINT("Error: cannot write to console\n");
        startProbeNextDevice();
    }
}

// -------------------------------   Other helper methods
bool PairUpWearPhoneImpl::checkForWearDevice() {
    const bool isWearDevice =
            mReply.contains("clockwork") &&
            !strncmp(mDeviceInProbing.c_str(), "emulator-", 9);

    if (isWearDevice) {
        DPRINT("found wear %s\n\n", mDeviceInProbing.c_str());
        mWearDevices.push_back(mDeviceInProbing);
    }

    return isWearDevice;
}

bool PairUpWearPhoneImpl::checkForCompatiblePhone() {
    const bool isCompatiblePhone = mReply.contains(kWearableAppName);

    if (isCompatiblePhone) {
        DPRINT("found compatible phone %s\n\n", mDeviceInProbing.c_str());
        mPhoneDevices.push_back(mDeviceInProbing);
    } else {
        const bool shouldTryAgainLater = mReply.contains("Error:") &&
            mReply.contains("Is the system running?");

        if (shouldTryAgainLater) mUnprobedDevices.push_back(mDeviceInProbing);
    }

    return isCompatiblePhone;
}

bool PairUpWearPhoneImpl::startReadConsole() {
    openConsoleConnection();

    if (mConsoleWatch->fd() < 0) {
        startProbeNextDevice();
        return false;
    } else {
        DPRINT("ready to read console greetings\n");
        switchToRead(&mConsoleWatch);
        return true;
    }
}

bool PairUpWearPhoneImpl::startWriteCommandToAdb(int queryType,
                                                 const char* message) {
    if (TRANSFER == queryType || FORWARDIP == queryType) {
        closeConnection(&mAdbWatch);
        openAdbConnection();
    }

    if (!mAdbWatch.get() || !message) {
        startProbeNextDevice();
        return false;
    }

    char buf2[1024];
    switch(queryType) {
        case TRANSFER:
            snprintf(buf2, sizeof(buf2), "host:transport:%s", message);
            break;
        case PROPERTY:
            snprintf(buf2, sizeof(buf2), "shell:getprop %s", message);
            break;
        case WEARABLE_APP_PKG:
            snprintf(buf2, sizeof(buf2), "shell:pm list packages %s", message);
            break;
        case FORWARDIP:
            snprintf(buf2, sizeof(buf2), "host-serial:%s:forward:tcp:5601;tcp:5601", message);
            break;
        default:
            startProbeNextDevice();
            return false;
    }

    snprintf(mWriteBuffer, WRITE_BUFFER_SIZE, "%04x%s", (unsigned)(::strlen(buf2)), buf2);
    DPRINT("sending query '%s' to adb\n", mWriteBuffer);
    mAsyncWriter.reset(mWriteBuffer, ::strlen(mWriteBuffer), mAdbWatch.get());
    switchToWrite(&mAdbWatch);
    return true;
}

bool PairUpWearPhoneImpl::completeWriteCommandToAdb() {
    AsyncStatus status = mAsyncWriter.run();

    if (status == kAsyncError) {
        startProbeNextDevice();
        return false;
    } else if (status == kAsyncAgain) {
        return false;
    }
    return true;
}

bool PairUpWearPhoneImpl::startReadHeaderFromAdb() {
    if (!mAdbWatch.get()) {
        startProbeNextDevice();
        return false;
    }

    mReply.clear();
    mReadBuffer[4]='\0';
    mAsyncReader.reset(mReadBuffer, 4, mAdbWatch.get());
    switchToRead(&mAdbWatch);
    return true;
}

bool PairUpWearPhoneImpl::completeReadHeaderFromAdb() {
    AsyncStatus status = mAsyncReader.run();

    if (status == kAsyncAgain) {
        return false;
    } else if (status == kAsyncCompleted && !strncmp("OKAY", mReadBuffer,4)) {
        DPRINT("received mesg from adb host:%s\n", mReadBuffer);
        return true;
    } else {
        startProbeNextDevice();
        return false;
    }
}

bool PairUpWearPhoneImpl::completeReadAllDataFromAdb() {
    if (!mAdbWatch.get()) {
        startProbeNextDevice();
        return false;
    }

    char buff[1024];
    ssize_t size = socketRecv(mAdbWatch->fd(), buff, sizeof(buff));
    if (size < 0) {
        if (errno != EWOULDBLOCK && errno != EAGAIN) {
            startProbeNextDevice();
        }
        return false;
    } else if (size > 0) {
        mReply.append(buff, size);
        return false;
    }
    DPRINT("received mesg from adb host:%s\n", mReply.c_str());
    return true;
}

PairUpWearPhoneImpl::PairUpWearPhoneImpl(Looper* looper,
                                         const StringVector& devices,
                                         int adbHostPort) :
        mLooper(looper),
        mAdbHostPort(adbHostPort),
        mAdbWatch(),
        mConsolePort(-1),
        mConsoleWatch(),
        mUnprobedDevices(),
        mWearDevices(),
        mPhoneDevices(),
        mState(PAIRUP_ERROR),
        mAsyncReader(),
        mAsyncWriter(),
        mReadBuffer(static_cast<char*>(calloc(READ_BUFFER_SIZE,1))),
        mWriteBuffer(static_cast<char*>(calloc(WRITE_BUFFER_SIZE,1))),
        mReply() {

    updateDevices(devices);

    if (isDone()) {
        cleanUp();
    }
}

PairUpWearPhoneImpl::~PairUpWearPhoneImpl() {
    cleanUp();
    mLooper = 0;
}

void PairUpWearPhoneImpl::startProbeNextDevice() {
    closeConnection(&mAdbWatch);
    closeConnection(&mConsoleWatch);

    if (mUnprobedDevices.empty()) {
        mState = PAIRUP_ERROR;
        return;
    }

    mDeviceInProbing = mUnprobedDevices[0];
    mUnprobedDevices.pop();

    if (startWriteCommandToAdb(TRANSFER, mDeviceInProbing.c_str())) {
        mState = TO_GET_PRODUCT_NAME_INIT_XFER;
    } else {
        mState = PAIRUP_ERROR;
    }
}

void PairUpWearPhoneImpl::cleanUp() {
    closeConnection(&mAdbWatch);
    closeConnection(&mConsoleWatch);

    mUnprobedDevices.resize(0U);
    mPhoneDevices.resize(0U);
    mWearDevices.resize(0U);
    mReply.clear();
    if (mReadBuffer) {
        free(mReadBuffer);
        mReadBuffer = NULL;
    }
    if (mWriteBuffer) {
        free(mWriteBuffer);
        mWriteBuffer = NULL;
    }
    if (PAIRUP_SUCCESS == mState) {
        DPRINT("\nSUCCESS\n");
    } else if (PAIRUP_ALREADY_CLEANEDUP != mState) {
        DPRINT("\nFAIL\n");
    }
    mState = PAIRUP_ALREADY_CLEANEDUP;
    DPRINT("\nclean up\n\n");
    fflush(stdout); // actually, need to flush stdout
}

bool PairUpWearPhoneImpl::isDone() const {
    return (PAIRUP_ERROR == mState || PAIRUP_SUCCESS == mState);
}

void PairUpWearPhoneImpl::updateDevices(const StringVector& devices) {
    if (devices.size() < 2) {
        DPRINT("Error: There are less than two devices, cannot proceed.\n");
        mState = PAIRUP_ERROR;
        return;
    }
    DPRINT("start pairing up wear to phone\n");
    StringVector deviceQueue;
    for (size_t i = 0; i < devices.size(); ++i) {
        deviceQueue.push_back(devices[i]);
    }
    mUnprobedDevices.swap(&deviceQueue);
    startProbeNextDevice();
}

void PairUpWearPhoneImpl::startConnectWearAndPhone() {
    closeConnection(&mAdbWatch);
    closeConnection(&mConsoleWatch);

    if (mPhoneDevices.empty() || mWearDevices.empty()) {
        startProbeNextDevice();
        return;
    }

    String phone = mPhoneDevices[0];
    mPhoneDevices.pop();
    const char emu[] = "emulator-";
    const int sz = sizeof(emu) - 1;
    if (strncmp(emu, phone.c_str(), sz) != 0) {
        // real phone
        if (startWriteCommandToAdb(FORWARDIP, phone.c_str())) {
            mState = TO_FORWARD_IP_SEND_CMD;
        }
    } else {
        // emulator
        mConsolePort = atoi(phone.c_str() + sz);
        if (startReadConsole()) {
            mState = TO_READ_GREETINGS_FROM_CONSOLE;
        }
    }
}

//-----------------------            helper methods

void PairUpWearPhoneImpl::openAdbConnection() {
    mReply.clear();
    if (!openConnection(mAdbHostPort,
                        &mAdbWatch,
                        _on_adb_server_socket_fd)) {
        mState = PAIRUP_ERROR;
    }
}

void PairUpWearPhoneImpl::openConsoleConnection() {
    mReply.clear();
    if (!openConnection(mConsolePort,
                        &mConsoleWatch,
                        _on_emulator_console_socket_fd)) {
        mState = PAIRUP_ERROR;
    }
}

void PairUpWearPhoneImpl::closeConnection(FdWatch* watch) {
    if (watch->get()) {
        (*watch)->dontWantRead();
        (*watch)->dontWantWrite();
        socketClose((*watch)->fd());
        watch->reset(NULL);
    }
}

bool PairUpWearPhoneImpl::openConnection(int port,
                                         FdWatch* watch,
                                         Looper::FdWatch::Callback callback) {
    int so = socketTcpLoopbackClient(port);
    if (so < 0) {
        DPRINT("failed to open up connection to port %d\n", port);
        watch->reset(NULL);
        return false;
    }
    socketSetNonBlocking(so);
    watch->reset(mLooper->createFdWatch(so, callback, this));
    DPRINT("successfully opened up connection to port %d\n", port);
    return true;
}

// ------------------------------------------------------------------
//
//       PairUpWearPhone  implementation
//
// ------------------------------------------------------------------

PairUpWearPhone::PairUpWearPhone(Looper* looper,
                                 const StringVector& devices,
                                 int adbHostPort) :
    mPairUpWearPhoneImpl (new PairUpWearPhoneImpl(looper,
                                                  devices,
                                                  adbHostPort)) {
    //VERBOSE_ENABLE(adb);
}

PairUpWearPhone::~PairUpWearPhone() {
    delete mPairUpWearPhoneImpl;
}

bool PairUpWearPhone::isDone() const {
    return mPairUpWearPhoneImpl->isDone();
}

} // namespace wear
} // namespace android
