// Copyright 2017 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.

#pragma once

#include <ddk/binding.h>
#include <ddk/device.h>
#include <fbl/intrusive_double_list.h>
#include <fbl/string.h>
#include <fbl/unique_ptr.h>
#include <fbl/vector.h>
#include <fuchsia/device/manager/c/fidl.h>
#include <lib/async/cpp/wait.h>
#include <lib/svc/outgoing.h>
#include <lib/zx/channel.h>
#include <lib/zx/event.h>
#include <lib/zx/job.h>
#include <lib/zx/process.h>
#include <lib/zx/vmo.h>

#include <utility>

#include "boot-args.h"
#include "composite-device.h"
#include "devhost.h"
#include "device.h"
#include "driver.h"
#include "metadata.h"
#include "suspend-task.h"
#include "vmo-writer.h"

namespace devmgr {

class DevhostLoaderService;

class SuspendContext {
public:
    enum class Flags : uint32_t {
        kRunning = 0u,
        kSuspend = 1u,
    };

    SuspendContext() = default;

    SuspendContext(Flags flags, uint32_t sflags, zx::vmo kernel = zx::vmo(),
                   zx::vmo bootdata = zx::vmo())
        : flags_(flags), sflags_(sflags), kernel_(std::move(kernel)),
          bootdata_(std::move(bootdata)) {}

    ~SuspendContext() {}

    SuspendContext(SuspendContext&&) = default;
    SuspendContext& operator=(SuspendContext&&) = default;

    void set_task(fbl::RefPtr<SuspendTask> task) { task_ = std::move(task); }

    Flags flags() const { return flags_; }
    void set_flags(Flags flags) { flags_ = flags; }
    uint32_t sflags() const { return sflags_; }

    const zx::vmo& kernel() const { return kernel_; }
    const zx::vmo& bootdata() const { return bootdata_; }

private:
    fbl::RefPtr<SuspendTask> task_;

    Flags flags_ = Flags::kRunning;

    // suspend flags
    uint32_t sflags_ = 0u;

    // mexec arguments
    zx::vmo kernel_;
    zx::vmo bootdata_;
};

// Values parsed out of argv.  All paths described below are absolute paths.
struct DevmgrArgs {
    // Load drivers from these directories.  If this is empty, the default will
    // be used.
    fbl::Vector<const char*> driver_search_paths;
    // Load the drivers with these paths.  The specified drivers do not need to
    // be in directories in |driver_search_paths|.
    fbl::Vector<const char*> load_drivers;
    // Use this driver as the sys_device driver.  If nullptr, the default will
    // be used.
    const char* sys_device_driver = nullptr;
    // Select whether to launch a new svchost or to just use the system provided
    // /svc directory.
    bool use_system_svchost = false;
    // Disables the block watcher if set to true. This can be used for testing purposes,
    // where it is not necessary to have the block watcher running.
    bool disable_block_watcher = false;
    // Disables the netsvc if set to true. This can be used for testing purposes,
    // where it is not necessary to have the netsvc running.
    bool disable_netsvc = false;
};

struct CoordinatorConfig {
    // Initial root resource from the kernel.
    zx::resource root_resource;
    // Job for all devhosts.
    zx::job devhost_job;
    // Event that controls the fshost.
    zx::event fshost_event;
    // Async dispatcher for the coordinator.
    async_dispatcher_t* dispatcher;
    // Boot arguments from the Arguments service.
    const devmgr::BootArgs* boot_args;
    // If true, netsvc is disabled and will not start.
    bool disable_netsvc;
    // Whether we require /system.
    bool require_system;
    // Whether we require ASan drivers.
    bool asan_drivers;
    // Whether to reboot the device when suspend does not finish on time.
    bool suspend_fallback;
    // Whether to print out debugging when suspend does not finish on time.
    bool suspend_debug;
};

class Coordinator {
public:
    Coordinator(const Coordinator&) = delete;
    Coordinator& operator=(const Coordinator&) = delete;
    Coordinator(Coordinator&&) = delete;
    Coordinator& operator=(Coordinator&&) = delete;

    explicit Coordinator(CoordinatorConfig config);
    ~Coordinator();

    zx_status_t InitializeCoreDevices(const char* sys_device_driver);
    bool InSuspend() const;

    zx_status_t ScanSystemDrivers();
    void BindDrivers();
    void UseFallbackDrivers();
    void DriverAdded(Driver* drv, const char* version);
    void DriverAddedInit(Driver* drv, const char* version);
    zx_status_t LibnameToVmo(const fbl::String& libname, zx::vmo* out_vmo) const;

    // Function that is invoked to request a driver try to bind to a device
    using AttemptBindFunc =
            fit::function<zx_status_t(const Driver* drv, const fbl::RefPtr<Device>& dev)>;

    // Attempts to bind the given driver to the given device.  Returns ZX_OK on
    // success, ZX_ERR_NEXT if the driver is not capable of binding to the device,
    // and a different error if the driver was capable of binding but failed to bind.
    zx_status_t BindDriverToDevice(const fbl::RefPtr<Device>& dev, const Driver* drv,
                                   bool autobind) {
        return BindDriverToDevice(dev, drv, autobind,
                                  fit::bind_member(this, &Coordinator::AttemptBind));
    }

    // The same as above, but the given function is called to perform the
    // bind attempt.
    zx_status_t BindDriverToDevice(const fbl::RefPtr<Device>& dev, const Driver* drv,
                                   bool autobind, const AttemptBindFunc& attempt_bind);

    // Used to implement fuchsia::device::manager::Coordinator.
    zx_status_t AddDevice(const fbl::RefPtr<Device>& parent, zx::channel rpc,
                          const uint64_t* props_data, size_t props_count, fbl::StringPiece name,
                          uint32_t protocol_id, fbl::StringPiece driver_path, fbl::StringPiece args,
                          bool invisible, zx::channel client_remote,
                          fbl::RefPtr<Device>* new_device);
    zx_status_t RemoveDevice(const fbl::RefPtr<Device>& dev, bool forced);
    zx_status_t MakeVisible(const fbl::RefPtr<Device>& dev);
    zx_status_t BindDevice(const fbl::RefPtr<Device>& dev, fbl::StringPiece drvlibname,
                           bool new_device);
    zx_status_t GetTopologicalPath(const fbl::RefPtr<const Device>& dev, char* out,
                                   size_t max) const;
    zx_status_t LoadFirmware(const fbl::RefPtr<Device>& dev, const char* path, zx::vmo* vmo,
                             size_t* size);

    zx_status_t GetMetadata(const fbl::RefPtr<Device>& dev, uint32_t type, void* buffer,
                            size_t buflen, size_t* size);
    zx_status_t GetMetadataSize(const fbl::RefPtr<Device>& dev, uint32_t type, size_t* size) {
        return GetMetadata(dev, type, nullptr, 0, size);
    }
    zx_status_t AddMetadata(const fbl::RefPtr<Device>& dev, uint32_t type, const void* data,
                            uint32_t length);
    zx_status_t PublishMetadata(const fbl::RefPtr<Device>& dev, const char* path, uint32_t type,
                                const void* data, uint32_t length);
    zx_status_t AddCompositeDevice(const fbl::RefPtr<Device>& dev, 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);

    void DmMexec(zx::vmo kernel, zx::vmo bootdata);

    void HandleNewDevice(const fbl::RefPtr<Device>& dev);
    zx_status_t PrepareProxy(const fbl::RefPtr<Device>& dev, Devhost* target_devhost);

    void DumpState(VmoWriter* vmo) const;

    const zx::resource& root_resource() const { return config_.root_resource; }
    const zx::event& fshost_event() const { return config_.fshost_event; }
    async_dispatcher_t* dispatcher() const { return config_.dispatcher; }
    const devmgr::BootArgs& boot_args() const { return *config_.boot_args; }
    bool disable_netsvc() const { return config_.disable_netsvc; }
    bool require_system() const { return config_.require_system; }
    bool suspend_fallback() const { return config_.suspend_fallback; }
    bool suspend_debug() const { return config_.suspend_debug; }

    void set_running(bool running) { running_ = running; }
    bool system_available() const { return system_available_; }
    void set_system_available(bool system_available) { system_available_ = system_available; }
    bool system_loaded() const { return system_loaded_; }
    void set_loader_service(DevhostLoaderService* loader_service) {
        loader_service_ = loader_service;
    }

    fbl::DoublyLinkedList<Driver*, Driver::Node>& drivers() { return drivers_; }
    const fbl::DoublyLinkedList<Driver*, Driver::Node>& drivers() const { return drivers_; }
    fbl::DoublyLinkedList<fbl::RefPtr<Device>, Device::AllDevicesNode>& devices() {
        return devices_;
    }
    const fbl::DoublyLinkedList<fbl::RefPtr<Device>, Device::AllDevicesNode>& devices() const {
        return devices_;
    }

    void AppendPublishedMetadata(fbl::unique_ptr<Metadata> metadata) {
        published_metadata_.push_back(std::move(metadata));
    }

    const fbl::RefPtr<Device>& root_device() { return root_device_; }
    const fbl::RefPtr<Device>& misc_device() { return misc_device_; }
    const fbl::RefPtr<Device>& sys_device() { return sys_device_; }
    const fbl::RefPtr<Device>& test_device() { return test_device_; }

    void Suspend(uint32_t flags);

    SuspendContext& suspend_context() { return suspend_context_; }
    const SuspendContext& suspend_context() const { return suspend_context_; }

    zx_status_t BindFidlServiceProxy(zx::channel listen_on);

    zx_status_t BindOutgoingServices(zx::channel listen_on);

    const Driver* component_driver() const { return component_driver_; }

    void ReleaseDevhost(Devhost* dh);

    // This method is public only for the test suite.
    zx_status_t BindDriver(Driver* drv, const AttemptBindFunc& attempt_bind);
private:
    CoordinatorConfig config_;
    bool running_ = false;
    bool launched_first_devhost_ = false;
    bool system_available_ = false;
    bool system_loaded_ = false;
    DevhostLoaderService* loader_service_ = nullptr;


    // Services offered to the rest of the system.
    svc::Outgoing outgoing_services_;

    // All Drivers
    fbl::DoublyLinkedList<Driver*, Driver::Node> drivers_;

    // Drivers to try last
    fbl::DoublyLinkedList<Driver*, Driver::Node> fallback_drivers_;

    // List of drivers loaded from /system by system_driver_loader()
    fbl::DoublyLinkedList<Driver*, Driver::Node> system_drivers_;

    // All Devices (excluding static immortal devices)
    fbl::DoublyLinkedList<fbl::RefPtr<Device>, Device::AllDevicesNode> devices_;

    // All DevHosts
    fbl::DoublyLinkedList<Devhost*, Devhost::AllDevhostsNode> devhosts_;

    // All composite devices
    fbl::DoublyLinkedList<std::unique_ptr<CompositeDevice>, CompositeDevice::Node>
            composite_devices_;

    fbl::RefPtr<Device> root_device_;
    fbl::RefPtr<Device> misc_device_;
    fbl::RefPtr<Device> sys_device_;
    fbl::RefPtr<Device> test_device_;

    SuspendContext suspend_context_;

    fbl::DoublyLinkedList<fbl::unique_ptr<Metadata>, Metadata::Node> published_metadata_;

    // Once the special component driver is loaded, this will refer to it.  This
    // driver is used for binding against components of composite devices
    const Driver* component_driver_ = nullptr;

    void DumpDevice(VmoWriter* vmo, const Device* dev, size_t indent) const;
    void DumpDeviceProps(VmoWriter* vmo, const Device* dev) const;
    void DumpGlobalDeviceProps(VmoWriter* vmo) const;
    void DumpDrivers(VmoWriter* vmo) const;

    void BuildSuspendList();
    void Suspend(SuspendContext ctx);

    fbl::unique_ptr<Driver> ValidateDriver(fbl::unique_ptr<Driver> drv);
    const Driver* LibnameToDriver(const fbl::String& libname) const;

    zx_status_t NewDevhost(const char* name, Devhost* parent, Devhost** out);

    zx_status_t BindDriver(Driver* drv) {
        return BindDriver(drv, fit::bind_member(this, &Coordinator::AttemptBind));
    }
    zx_status_t AttemptBind(const Driver* drv, const fbl::RefPtr<Device>& dev);
    void BindSystemDrivers();
    void DriverAddedSys(Driver* drv, const char* version);

    zx_status_t GetMetadataRecurse(const fbl::RefPtr<Device>& dev, uint32_t type, void* buffer,
                                   size_t buflen, size_t* size);

    void InitOutgoingServices();
};

bool driver_is_bindable(const Driver* drv, uint32_t protocol_id,
                        const fbl::Array<const zx_device_prop_t>& props, bool autobind);

// Path to driver that should be bound to components of composite devices
extern const char* kComponentDriverPath;

zx_status_t fidl_DmMexec(void* ctx, zx_handle_t raw_kernel, zx_handle_t raw_bootdata);
zx_status_t fidl_DirectoryWatch(void* ctx, uint32_t mask, uint32_t options,
                                zx_handle_t raw_watcher, fidl_txn_t* txn);

} // namespace devmgr
