// 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 "driver_host.h"
#include "zx_device.h"

namespace {

class CompositeDeviceInstance {
 public:
  CompositeDeviceInstance(zx_device_t* zxdev, CompositeFragments&& fragments)
      : zxdev_(zxdev), fragments_(std::move(fragments)) {}

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

  uint32_t GetFragmentCount() { return static_cast<uint32_t>(fragments_.size()); }

  void GetFragments(composite_device_fragment_t* comp_list, size_t comp_count,
                    size_t* comp_actual) {
    size_t actual = std::min(comp_count, fragments_.size());
    for (size_t i = 0; i < actual; ++i) {
      strncpy(comp_list[i].name, fragments_[i].name.c_str(), 32);
      comp_list[i].device = fragments_[i].device.get();
    }
    *comp_actual = actual;
  }

  bool GetFragment(const char* name, zx_device_t** out) {
    for (auto& fragment : fragments_) {
      if (strncmp(name, fragment.name.c_str(), 32) == 0) {
        *out = fragment.device.get();
        return true;
      }
    }
    return false;
  }

  void Release() { delete this; }

  void Unbind() {
    for (auto& fragment : fragments_) {
      // Drop the reference to the composite device.
      fragment.device->take_composite();
    }
    fragments_.reset();
    device_unbind_reply(zxdev_);
  }

  const CompositeFragments& fragments() { return fragments_; }

 private:
  zx_device_t* zxdev_;
  CompositeFragments fragments_;
};

}  // namespace

// Get the placeholder driver structure for the composite driver
fbl::RefPtr<zx_driver> GetCompositeDriver(DriverHostContext* ctx) {
  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("<internal:composite>", ctx->inspect().drivers(), &composite);
    if (status != ZX_OK) {
      return nullptr;
    }
    composite->set_name("internal:composite");
  }
  return composite;
}

zx_status_t InitializeCompositeDevice(const fbl::RefPtr<zx_device>& dev,
                                      CompositeFragments&& fragments) {
  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_fragment_count = [](void* ctx) {
      return static_cast<CompositeDeviceInstance*>(ctx)->GetFragmentCount();
    };
    ops.get_fragments = [](void* ctx, composite_device_fragment_t* comp_list, size_t comp_count,
                           size_t* comp_actual) {
      static_cast<CompositeDeviceInstance*>(ctx)->GetFragments(comp_list, comp_count, comp_actual);
    };
    ops.get_fragment = [](void* ctx, const char* name, zx_device_t** out) -> bool {
      return static_cast<CompositeDeviceInstance*>(ctx)->GetFragment(name, out);
    };
    return ops;
  }();

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

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

  for (auto& fragment : new_device->fragments()) {
    fragment.device->set_composite(composite);
  }

  dev->set_protocol_id(ZX_PROTOCOL_COMPOSITE);
  dev->protocol_ops = &composite_ops;
  dev->set_ops(&composite_device_ops);
  dev->ctx = new_device.release();
  // Flag that when this is cleaned up, we should run its release hook.
  dev->set_flag(DEV_FLAG_ADDED);
  return ZX_OK;
}

CompositeDevice::~CompositeDevice() = default;
