// 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_metadata_t> devices_metadata_;
    fbl::Vector<pbus_dev_t> devices_;

    ddk::PBusProtocolClient pbus_;
    thrd_t thread_;
};


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

// This function must be kept updated with the function that serializes the date.
// This function is driver_integration_test::GetBootItem.
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;
    }

    size_t metadata_offset = (device_list->count * sizeof(DeviceEntry)) + sizeof(DeviceList);
    for (size_t i = 0; i < device_list->count; i++) {
        const auto& entry = device_list->list[i];
        // Create the device.
        pbus_dev_t device = {};
        device.name = entry.name;
        device.vid = entry.vid;
        device.pid = entry.pid;
        device.did = entry.did;

        //Create the metadata.
        pbus_metadata_t metadata = {};
        metadata.type = DEVICE_METADATA_TEST;
        metadata.data_size = entry.metadata_size;
        metadata.data_buffer = metadata_.get() + metadata_offset;
        metadata_offset += metadata.data_size;

        // Store the metadata and link the device to it.
        devices_metadata_.push_back(std::move(metadata));
        device.metadata_count = 1;
        device.metadata_list = &devices_metadata_[devices_metadata_.size() - 1];


        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)
