// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <memory>

#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <threads.h>

#include <ddk/binding.h>
#include <ddk/debug.h>
#include <ddk/device.h>
#include <ddk/driver.h>
#include <ddk/metadata.h>
#include <ddk/metadata/test.h>
#include <ddk/platform-defs.h>
#include <ddktl/device.h>
#include <ddktl/protocol/platform/bus.h>

#include <fbl/array.h>
#include <fbl/vector.h>
#include <zircon/process.h>
#include <zircon/syscalls.h>
#include <zircon/assert.h>

namespace board_test {

class TestBoard;
using TestBoardType = ddk::Device<TestBoard>;

// This is the main class for the platform bus driver.
class TestBoard : public TestBoardType {
public:
    explicit TestBoard(zx_device_t* parent, pbus_protocol_t* pbus)
        : TestBoardType(parent), pbus_(pbus) {}

    static zx_status_t Create(void* ctx, zx_device_t* parent);

    // Device protocol implementation.
    void DdkRelease();

private:
    TestBoard(const TestBoard&) = delete;
    TestBoard& operator=(const TestBoard&) = delete;
    TestBoard(TestBoard&&) = delete;
    TestBoard& operator=(TestBoard&&) = delete;

    // Fetches devices to load from metadata and deserializes into a vector of
    // pbus_dev_t.
    zx_status_t FetchAndDeserialize();
    zx_status_t Start();
    int Thread();

    fbl::Array<uint8_t> metadata_;

    fbl::Vector<pbus_dev_t> devices_;

    ddk::PBusProtocolClient pbus_;
    thrd_t thread_;
};


void TestBoard::DdkRelease() {
    delete this;
}

zx_status_t TestBoard::FetchAndDeserialize() {
    size_t metadata_size;
    zx_status_t status = DdkGetMetadataSize(DEVICE_METADATA_BOARD_PRIVATE, &metadata_size);
    if (status != ZX_OK) {
        return status;
    }
    if (metadata_size < sizeof(DeviceList)) {
        return ZX_ERR_BUFFER_TOO_SMALL;
    }

    fbl::AllocChecker ac;
    auto metadata = new (&ac) uint8_t[metadata_size];
    if (!ac.check()) {
        return ZX_ERR_NO_MEMORY;
    }
    metadata_.reset(metadata, metadata_size);

    size_t actual;
    status = DdkGetMetadata(DEVICE_METADATA_BOARD_PRIVATE, metadata, metadata_size, &actual);
    if (status != ZX_OK) {
        return status;
    }
    if (actual != metadata_size) {
        return ZX_ERR_INTERNAL;
    }

    const auto* device_list = reinterpret_cast<DeviceList*>(metadata);
    if (metadata_size < sizeof(DeviceList) + device_list->count * sizeof(DeviceEntry)) {
        return ZX_ERR_INTERNAL;
    }

    devices_.reserve(device_list->count, &ac);
    if (!ac.check()) {
        return ZX_ERR_NO_MEMORY;
    }

    for (size_t i = 0; i < device_list->count; i++) {
        const auto& entry = device_list->list[i];
        pbus_dev_t device = {};
        device.name = entry.name;
        device.vid = entry.vid;
        device.pid = entry.pid;
        device.did = entry.did;

        devices_.push_back(device);
    }

    return ZX_OK;
}

int TestBoard::Thread() {
    for (const auto& device : devices_) {
        zx_status_t status = pbus_.DeviceAdd(&device);
        if (status != ZX_OK) {
            zxlogf(ERROR, "Failed to add device.\n");
        }
    }
    return 0;
}

zx_status_t TestBoard::Start() {
    int rc = thrd_create_with_name(&thread_,
                                   [](void* arg) -> int {
                                       return reinterpret_cast<TestBoard*>(arg)->Thread();
                                   },
                                   this,
                                   "test-board-start-thread");
    if (rc != thrd_success) {
        return ZX_ERR_INTERNAL;
    }
    return ZX_OK;
}

zx_status_t TestBoard::Create(void* ctx, zx_device_t* parent) {
    pbus_protocol_t pbus;
    if (device_get_protocol(parent, ZX_PROTOCOL_PBUS, &pbus) != ZX_OK) {
        return ZX_ERR_NOT_SUPPORTED;
    }

    auto board = std::make_unique<TestBoard>(parent, &pbus);

    zx_status_t status = board->FetchAndDeserialize();
    if (status != ZX_OK) {
        zxlogf(ERROR, "TestBoard::Create: FetchAndDeserialize failed: %d\n", status);
        return status;
    }

    status = board->DdkAdd("test-board", DEVICE_ADD_NON_BINDABLE);
    if (status != ZX_OK) {
        zxlogf(ERROR, "TestBoard::Create: DdkAdd failed: %d\n", status);
        return status;
    }

    status = board->Start();
    if (status == ZX_OK) {
      // devmgr is now in charge of the device.
      __UNUSED auto* dummy = board.release();
    }

    return status;
}

static zx_driver_ops_t driver_ops = [](){
    zx_driver_ops_t ops;
    ops.version = DRIVER_OPS_VERSION;
    ops.bind = TestBoard::Create;
    return ops;
}();

} // namespace board_test

ZIRCON_DRIVER_BEGIN(test_bus, board_test::driver_ops, "zircon", "0.1", 3)
    BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_PBUS),
    BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_TEST),
    BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_PID, PDEV_PID_INTEGRATION_TEST),
ZIRCON_DRIVER_END(test_bus)
