// 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 "composite-device.h"

#include <algorithm>
#include <ddk/protocol/composite.h>
#include <fbl/auto_lock.h>
#include <fbl/mutex.h>
#include "devhost.h"
#include "zx-device.h"

namespace devmgr {

namespace {

class CompositeDeviceInstance {
public:
    CompositeDeviceInstance(zx_device_t* zxdev, CompositeComponents&& components)
            : zxdev_(zxdev), components_(std::move(components)) { }

    static zx_status_t Create(fbl::RefPtr<zx_device> zxdev, CompositeComponents&& components,
                              std::unique_ptr<CompositeDeviceInstance>* device) {
        // Leak a reference to the zxdev here.  It will be cleaned up by the
        // device_remove() in Unbind().
        auto dev = std::make_unique<CompositeDeviceInstance>(zxdev.leak_ref(),
                                                             std::move(components));
        *device = std::move(dev);
        return ZX_OK;
    }

    uint32_t GetComponentCount() {
        return static_cast<uint32_t>(components_.size());
    }

    void GetComponents(zx_device_t** comp_list, size_t comp_count, size_t* comp_actual) {
        size_t actual = std::min(comp_count, components_.size());
        for (size_t i = 0; i < actual; ++i) {
            comp_list[i] = components_[i].get();
        }
        *comp_actual = actual;
    }

    void Release() {
        delete this;
    }

    void Unbind() {
        components_.reset();
        device_remove(zxdev_);
    }

    const CompositeComponents& components() { return components_; }
private:
    zx_device_t* zxdev_;
    CompositeComponents components_;
};

// Get the placeholder driver structure for the composite driver
fbl::RefPtr<zx_driver> GetCompositeDriver() {
    static fbl::Mutex lock;
    static fbl::RefPtr<zx_driver> composite TA_GUARDED(lock);

    fbl::AutoLock guard(&lock);
    if (composite == nullptr) {
        zx_status_t status = zx_driver::Create(&composite);
        if (status != ZX_OK) {
            return nullptr;
        }
        composite->set_name("internal:composite");
        composite->set_libname("<internal:composite>");
    }
    return composite;
}

} // namespace

zx_status_t InitializeCompositeDevice(const fbl::RefPtr<zx_device>& dev,
                                      CompositeComponents&& components) {
    static const zx_protocol_device_t composite_device_ops = []() {
        zx_protocol_device_t ops = {};
        ops.unbind = [](void* ctx) { static_cast<CompositeDeviceInstance*>(ctx)->Unbind(); };
        ops.release = [](void* ctx) { static_cast<CompositeDeviceInstance*>(ctx)->Release(); };
        return ops;
    }();
    static composite_protocol_ops_t composite_ops = []() {
        composite_protocol_ops_t ops = {};
        ops.get_component_count = [](void* ctx) {
            return static_cast<CompositeDeviceInstance*>(ctx)->GetComponentCount();
        };
        ops.get_components = [](void* ctx, zx_device_t** comp_list, size_t comp_count,
                                size_t* comp_actual) {
            static_cast<CompositeDeviceInstance*>(ctx)->GetComponents(comp_list, comp_count,
                                                                      comp_actual);
        };
        return ops;
    }();

    auto driver = GetCompositeDriver();
    if (driver == nullptr) {
        return ZX_ERR_INTERNAL;
    }

    auto composite = fbl::MakeRefCounted<CompositeDevice>(dev);

    std::unique_ptr<CompositeDeviceInstance> new_device;
    zx_status_t status = CompositeDeviceInstance::Create(dev, std::move(components),
                                                         &new_device);
    if (status != ZX_OK) {
        return status;
    }

    for (auto& component : new_device->components()) {
        component->set_composite(composite);
    }

    dev->protocol_id = ZX_PROTOCOL_COMPOSITE;
    dev->protocol_ops = &composite_ops;
    dev->driver = driver.get();
    dev->ops = &composite_device_ops;
    dev->ctx = new_device.release();
    // Flag that when this is cleaned up, we should run its release hook.
    dev->flags |= DEV_FLAG_ADDED;
    return ZX_OK;
}

CompositeDevice::~CompositeDevice() = default;

} // namespace devmgr
