// 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 <utility>
#include <zircon/status.h>
#include "../shared/log.h"
#include "binding-internal.h"
#include "coordinator.h"
#include "fidl.h"

namespace devmgr {

// CompositeDevice methods

CompositeDevice::CompositeDevice(fbl::String name, fbl::Array<const zx_device_prop_t> properties,
                                 uint32_t components_count, uint32_t coresident_device_index)
    : name_(std::move(name)), properties_(std::move(properties)),
      components_count_(components_count), coresident_device_index_(coresident_device_index) {
}

CompositeDevice::~CompositeDevice() = default;

zx_status_t CompositeDevice::Create(const fbl::StringPiece& name,
                                    const zx_device_prop_t* props_data, size_t props_count,
                                    const fuchsia_device_manager_DeviceComponent* components,
                                    size_t components_count, uint32_t coresident_device_index,
                                    std::unique_ptr<CompositeDevice>* out) {
    if (components_count > UINT32_MAX) {
        return ZX_ERR_INVALID_ARGS;
    }

    fbl::String name_obj(name);
    fbl::Array<zx_device_prop_t> properties(new zx_device_prop_t[props_count], props_count);
    memcpy(properties.get(), props_data, props_count * sizeof(props_data[0]));

    auto dev = std::make_unique<CompositeDevice>(std::move(name), std::move(properties),
                                                 components_count, coresident_device_index);
    for (uint32_t i = 0; i < components_count; ++i) {
        const auto& fidl_component = components[i];
        size_t parts_count = fidl_component.parts_count;
        fbl::Array<ComponentPartDescriptor> parts(new ComponentPartDescriptor[parts_count],
                                                  parts_count);
        for (size_t j = 0; j < parts_count; ++j) {
            const auto& fidl_part = fidl_component.parts[j];
            size_t program_count = fidl_part.match_program_count;
            fbl::Array<zx_bind_inst_t> match_program(new zx_bind_inst_t[program_count],
                                                    program_count);
            static_assert(sizeof(zx_bind_inst_t) == sizeof(fidl_part.match_program[0]));
            memcpy(match_program.get(), fidl_part.match_program,
                   sizeof(zx_bind_inst_t) * program_count);
            parts[j] = { std::move(match_program) };
        }

        auto component = std::make_unique<CompositeDeviceComponent>(dev.get(), i, std::move(parts));
        dev->unbound_.push_back(std::move(component));
    }
    *out = std::move(dev);
    return ZX_OK;
}

bool CompositeDevice::TryMatchComponents(const fbl::RefPtr<Device>& dev, size_t* index_out) {
    for (auto itr = bound_.begin(); itr != bound_.end(); ++itr) {
        if (itr->TryMatch(dev)) {
            log(ERROR,
                "devcoordinator: ambiguous composite bind! composite='%s', dev1='%s', dev2='%s'\n",
                name_.data(), itr->bound_device()->name().data(), dev->name().data());
            return false;
        }
    }
    for (auto itr = unbound_.begin(); itr != unbound_.end(); ++itr) {
        if (itr->TryMatch(dev)) {
            log(SPEW, "devcoordinator: found match for composite='%s', dev='%s'\n",
                name_.data(), dev->name().data());
            *index_out = itr->index();
           return true;
        }
    }
    log(SPEW, "devcoordinator: no match for composite='%s', dev='%s'\n",
        name_.data(), dev->name().data());
    return false;
}

zx_status_t CompositeDevice::BindComponent(size_t index, const fbl::RefPtr<Device>& dev) {
    // Find the component we're binding
    CompositeDeviceComponent* component = nullptr;
    for (auto& unbound_component : unbound_) {
        if (unbound_component.index() == index) {
            component = &unbound_component;
            break;
        }
    }
    ZX_ASSERT_MSG(component != nullptr, "Attempted to bind component that wasn't unbound!\n");

    zx_status_t status = component->Bind(dev);
    if (status != ZX_OK) {
        return status;
    }
    bound_.push_back(unbound_.erase(*component));
    return ZX_OK;
}

zx_status_t CompositeDevice::TryAssemble() {
    ZX_ASSERT(device_ == nullptr);
    if (!unbound_.is_empty()) {
        return ZX_ERR_SHOULD_WAIT;
    }

    Devhost* devhost = nullptr;
    for (auto& component : bound_) {
        // Find the devhost to put everything in (if we don't find one, nullptr
        // means "a new devhost").
        if (component.index() == coresident_device_index_) {
            devhost = component.bound_device()->host();
        }
        // Make sure the component driver has created its device
        if (component.component_device() == nullptr) {
            return ZX_ERR_SHOULD_WAIT;
        }
    }

    Coordinator* coordinator = nullptr;
    uint64_t component_local_ids[fuchsia_device_manager_COMPONENTS_MAX] = {};

    // Create all of the proxies for the component devices, in the same process
    for (auto& component : bound_) {
        const auto& component_dev = component.component_device();
        auto bound_dev = component.bound_device();
        coordinator = component_dev->coordinator;

        // If the device we're bound to is proxied, we care about its proxy
        // rather than it, since that's the side that we communicate with.
        if (bound_dev->proxy()) {
            bound_dev = bound_dev->proxy();
        }

        // Check if we need to use the proxy.  If not, share a reference straight
        // to the target device rather than the instance of the component device
        // that bound to it.
        if (bound_dev->host() == devhost) {
            component_local_ids[component.index()] = bound_dev->local_id();
            continue;
        }

        // We need to create it.  Double check that we haven't ended up in a state
        // where the proxies would need to be in different processes.
        if (devhost != nullptr && component_dev->proxy() != nullptr &&
            component_dev->proxy()->host() != nullptr &&
            component_dev->proxy()->host() != devhost) {
            log(ERROR, "devcoordinator: cannot create composite, proxies in different processes\n");
            return ZX_ERR_BAD_STATE;
        }

        zx_status_t status = coordinator->PrepareProxy(component_dev, devhost);
        if (status != ZX_OK) {
            return status;
        }
        // If we hadn't picked a devhost, use the one that was created just now.
        if (devhost == nullptr) {
            devhost = component_dev->proxy()->host();
            ZX_ASSERT(devhost != nullptr);
        }
        // Stash the local ID after the proxy has been created
        component_local_ids[component.index()] = component_dev->proxy()->local_id();
    }

    zx::channel rpc_local, rpc_remote;
    zx_status_t status = zx::channel::create(0, &rpc_local, &rpc_remote);
    if (status != ZX_OK) {
        return status;
    }

    fbl::RefPtr<Device> new_device;
    status = Device::CreateComposite(coordinator, devhost, *this, std::move(rpc_local),
                                     &new_device);
    if (status != ZX_OK) {
        return status;
    }
    coordinator->devices().push_back(new_device);

    // Create the composite device in the devhost
    status = dh_send_create_composite_device(devhost, new_device.get(), *this, component_local_ids,
                                             std::move(rpc_remote));
    if (status != ZX_OK) {
        log(ERROR, "devcoordinator: create composite device request failed: %s\n",
            zx_status_get_string(status));
        return status;
    }

    device_ = std::move(new_device);
    device_->set_composite(this);

    status = device_->SignalReadyForBind();
    if (status != ZX_OK) {
        return status;
    }

    return ZX_OK;
}

void CompositeDevice::UnbindComponent(CompositeDeviceComponent* component) {
    // If the composite was fully instantiated, diassociate from it.  It will be
    // reinstantiated when this component is re-bound.
    if (device_ != nullptr) {
        Remove();
    }
    ZX_ASSERT(device_ == nullptr);
    ZX_ASSERT(component->composite() == this);
    unbound_.push_back(bound_.erase(*component));
}

void CompositeDevice::Remove() {
    device_->disassociate_from_composite();
    device_ = nullptr;
}

// CompositeDeviceComponent methods

CompositeDeviceComponent::CompositeDeviceComponent(CompositeDevice* composite, uint32_t index,
                                                   fbl::Array<const ComponentPartDescriptor> parts)
    : composite_(composite), index_(index), parts_(std::move(parts)) {
}

CompositeDeviceComponent::~CompositeDeviceComponent() = default;

bool CompositeDeviceComponent::TryMatch(const fbl::RefPtr<Device>& dev) {
    if (parts_.size() > UINT32_MAX) {
        return false;
    }
    auto match = ::devmgr::internal::MatchParts(dev, parts_.get(),
                                                static_cast<uint32_t>(parts_.size()));
    if (match != ::devmgr::internal::Match::One) {
        return false;
    }
    return true;
}

zx_status_t CompositeDeviceComponent::Bind(const fbl::RefPtr<Device>& dev) {
    ZX_ASSERT(bound_device_ == nullptr);

    zx_status_t status = dev->coordinator->BindDriverToDevice(
            dev, dev->coordinator->component_driver(), true /* autobind */);
    if (status != ZX_OK) {
        return status;
    }

    bound_device_ = dev;
    dev->set_component(this);
    return ZX_OK;
}

void CompositeDeviceComponent::Unbind() {
    ZX_ASSERT(bound_device_ != nullptr);
    composite_->UnbindComponent(this);
    // Drop our reference to the device added by the component driver
    component_device_ = nullptr;
    bound_device_->disassociate_from_composite();
    bound_device_ = nullptr;
}

} // namespace devmgr
