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

#pragma once

#include <ddk/device.h>
#include <fbl/array.h>
#include <fbl/ref_counted.h>
#include <fbl/string.h>
#include <lib/async/cpp/task.h>
#include <lib/async/cpp/wait.h>
#include <lib/zx/channel.h>
#include <variant>

#include "composite-device.h"
#include "metadata.h"
#include "../shared/async-loop-ref-counted-rpc-handler.h"

namespace devmgr {

class Coordinator;
class Devhost;
struct Devnode;
class SuspendContext;
class SuspendTask;

// clang-format off

// This device is never destroyed
#define DEV_CTX_IMMORTAL      0x01

// This device requires that children are created in a
// new devhost attached to a proxy device
#define DEV_CTX_MUST_ISOLATE  0x02

// This device may be bound multiple times
#define DEV_CTX_MULTI_BIND    0x04

// This device is bound and not eligible for binding
// again until unbound.  Not allowed on MULTI_BIND ctx.
#define DEV_CTX_BOUND         0x08

// Device has been remove()'d
#define DEV_CTX_DEAD          0x10

// Device is a proxy -- its "parent" is the device it's
// a proxy to.
#define DEV_CTX_PROXY         0x40

// Device is not visible in devfs or bindable.
// Devices may be created in this state, but may not
// return to this state once made visible.
#define DEV_CTX_INVISIBLE     0x80

// clang-format on

struct Device : public fbl::RefCounted<Device>, public AsyncLoopRefCountedRpcHandler<Device> {
    // Node for entry in device child list
    struct Node {
        static fbl::DoublyLinkedListNodeState<Device*>& node_state(Device& obj) {
            return obj.node_;
        }
    };

    struct DevhostNode {
        static fbl::DoublyLinkedListNodeState<Device*>& node_state(Device& obj) {
            return obj.devhost_node_;
        }
    };

    struct AllDevicesNode {
        static fbl::DoublyLinkedListNodeState<Device*>& node_state(Device& obj) {
            return obj.all_devices_node_;
        }
    };

    // This iterator provides access to a list of devices that does not provide
    // mechanisms for mutating that list.  With this, a user can get mutable
    // access to a device in the list.  This is achieved by making the linked
    // list iterator opaque. It is not safe to modify the underlying list while
    // this iterator is in use.
    template <typename IterType, typename DeviceType>
    class ChildListIterator {
    public:
        ChildListIterator() : state_(Done{}) {}
        explicit ChildListIterator(DeviceType* device)
                : state_(device->children_.begin()), device_(device) {
            SkipInvalidStates();
        }

        ChildListIterator operator++(int) {
            auto other = *this;
            ++*this;
            return other;
        }
        bool operator==(const ChildListIterator& other) const { return state_ == other.state_; }
        bool operator!=(const ChildListIterator& other) const { return !(state_ == other.state_); }

        // The iterator implementation for the child list.  This is the source of truth
        // for what devices are children of the device.
        ChildListIterator& operator++() {
            std::visit([this](auto&& arg) {
                using T = std::decay_t<decltype(arg)>;
                if constexpr (std::is_same_v<T, IterType>) {
                    ++arg;
                } else if constexpr (std::is_same_v<T, Composite>) {
                    state_ = Done{};
                } else if constexpr (std::is_same_v<T, Done>) {
                    state_ = Done{};
                }
            }, state_);
            SkipInvalidStates();
            return *this;
        }

        DeviceType& operator*() const {
            return std::visit([this](auto&& arg) -> DeviceType& {
                using T = std::decay_t<decltype(arg)>;
                if constexpr (std::is_same_v<T, IterType>) {
                    return *arg;
                } else if constexpr (std::is_same_v<T, Composite>) {
                    return *device_->parent_->component()->composite()->device();
                } else {
                    __builtin_trap();
                }
            }, state_);
        }
    private:
        // Advance the iterator to the next valid state or reach the done state.
        // This is used to handle advancement between the different state variants.
        void SkipInvalidStates() {
            bool more = true;
            while (more) {
                more = std::visit([this](auto&& arg) {
                    using T = std::decay_t<decltype(arg)>;
                    if constexpr (std::is_same_v<T, IterType>) {
                        // Check if there are any more children in the list.  If
                        // there are, we're in a valid state and can stop.
                        // Otherwise, advance to the next variant and check if
                        // it's a valid state.
                        if (arg != device_->children_.end()) {
                            return false;
                        }
                        state_ = Composite{};
                        return true;
                    } else if constexpr (std::is_same_v<T, Composite>) {
                        // Check if this device is an internal component device
                        // that bound to a composite component.  If it is, and
                        // the composite has been constructed, the iterator
                        // should yield the composite.
                        CompositeDeviceComponent* component = nullptr;
                        if (device_->parent_) {
                            component = device_->parent_->component();
                        }
                        if (component != nullptr && component->composite()->device() != nullptr) {
                            return false;
                        }
                        state_ = Done{};
                        return false;
                    } else if constexpr (std::is_same_v<T, Done>) {
                        return false;
                    }
                }, state_);
            }
        }

        struct Composite {
            bool operator==(Composite) const { return true; }
        };
        struct Done {
            bool operator==(Done) const { return true; }
        };
        std::variant<IterType, Composite, Done> state_;
        DeviceType* device_;
    };

    // This class exists to allow consumers of the Device class to write
    //   for (auto& child : dev->children())
    // and get mutable access to the children without getting mutable access to
    // the list.
    template <typename DeviceType, typename IterType>
    class ChildListIteratorFactory {
    public:
        explicit ChildListIteratorFactory(DeviceType* device) : device_(device) {}

        IterType begin() const { return IterType(device_); }
        IterType end() const { return IterType(); }

        bool is_empty() const { return begin() == end(); }
    private:
        DeviceType* device_;
    };

    Device(Coordinator* coord, fbl::String name, fbl::String libname, fbl::String args,
           fbl::RefPtr<Device> parent, uint32_t protocol_id, zx::channel client_remote);
    ~Device();

    // Create a new device with the given parameters.  This sets up its
    // relationship with its parent and devhost and adds its RPC channel to the
    // coordinator's async loop.  This does not add the device to the
    // coordinator's devices_ list, or trigger publishing
    static zx_status_t Create(Coordinator* coordinator, const fbl::RefPtr<Device>& parent,
                              fbl::String name, fbl::String driver_path, fbl::String args,
                              uint32_t protocol_id, fbl::Array<zx_device_prop_t> props,
                              zx::channel rpc, bool invisible, zx::channel client_remote,
                              fbl::RefPtr<Device>* device);
    static zx_status_t CreateComposite(Coordinator* coordinator, Devhost* devhost,
                                       const CompositeDevice& composite, zx::channel rpc,
                                       fbl::RefPtr<Device>* device);
    zx_status_t CreateProxy();

    static void HandleRpc(fbl::RefPtr<Device>&& dev, async_dispatcher_t* dispatcher,
                          async::WaitBase* wait, zx_status_t status,
                          const zx_packet_signal_t* signal);

    // We do not want to expose the list itself for mutation, even if the
    // children are allowed to be mutated.  We manage this by making the
    // iterator opaque.
    using NonConstChildListIterator =
            ChildListIterator<fbl::DoublyLinkedList<Device*, Node>::iterator, Device>;
    using ConstChildListIterator =
            ChildListIterator<fbl::DoublyLinkedList<Device*, Node>::const_iterator, const Device>;
    using NonConstChildListIteratorFactory =
            ChildListIteratorFactory<Device, NonConstChildListIterator>;
    using ConstChildListIteratorFactory =
            ChildListIteratorFactory<const Device, ConstChildListIterator>;
    NonConstChildListIteratorFactory children() {
        return NonConstChildListIteratorFactory(this);
    }
    ConstChildListIteratorFactory children() const {
        return ConstChildListIteratorFactory(this);
    }

    // Signal that this device is ready for bind to happen.  This should happen
    // either immediately after the device is created, if it's created visible,
    // or after it becomes visible.
    zx_status_t SignalReadyForBind(zx::duration delay = zx::sec(0));

    using SuspendCompletion = fit::function<void(zx_status_t)>;
    // Issue a Suspend request to this device.  When the response comes in, the
    // given completion will be invoked.
    zx_status_t SendSuspend(uint32_t flags, SuspendCompletion completion);

    // Break the relationship between this device object and its parent
    void DetachFromParent();

    // Sets the properties of this device.  Returns an error if the properties
    // array contains more than one property from the BIND_TOPO_* range.
    zx_status_t SetProps(fbl::Array<const zx_device_prop_t> props);
    const fbl::Array<const zx_device_prop_t>& props() const { return props_; }
    const zx_device_prop_t* topo_prop() const { return topo_prop_; }

    const fbl::RefPtr<Device>& parent() { return parent_; }
    fbl::RefPtr<const Device> parent() const { return parent_; }

    const fbl::RefPtr<Device>& proxy() { return proxy_; }
    fbl::RefPtr<const Device> proxy() const { return proxy_; }

    uint32_t protocol_id() const { return protocol_id_; }

    bool is_bindable() const {
        return !(flags & (DEV_CTX_BOUND | DEV_CTX_DEAD | DEV_CTX_INVISIBLE));
    }

    // If the device was bound as a component of a composite, this returns the
    // component's description.
    CompositeDeviceComponent* component() const {
        auto val = std::get_if<CompositeDeviceComponent*>(&composite_);
        return val ? *val : nullptr;
    }
    void set_component(CompositeDeviceComponent* component) {
        ZX_ASSERT(std::holds_alternative<UnassociatedWithComposite>(composite_));
        composite_ = component;
    }

    // If the device was created as a composite, this returns its description.
    CompositeDevice* composite() const {
        auto val = std::get_if<CompositeDevice*>(&composite_);
        return val ? *val : nullptr;
    }
    void set_composite(CompositeDevice* composite) {
        ZX_ASSERT(std::holds_alternative<UnassociatedWithComposite>(composite_));
        composite_ = composite;
    }
    void disassociate_from_composite() {
        composite_ = UnassociatedWithComposite{};
    }

    void set_host(Devhost* host);
    Devhost* host() const { return host_; }
    uint64_t local_id() const { return local_id_; }

    const fbl::DoublyLinkedList<fbl::unique_ptr<Metadata>, Metadata::Node>& metadata() const {
        return metadata_;
    }
    void AddMetadata(fbl::unique_ptr<Metadata> md) {
        metadata_.push_front(std::move(md));
    }

    // Creates a new suspend task if necessary and returns a reference to it.
    // If one is already in-progress, a reference to it is returned instead
    fbl::RefPtr<SuspendTask> RequestSuspendTask(uint32_t suspend_flags);
    // Run the completion for the outstanding suspend, if any.  This method is
    // only exposed currently because RemoveDevice is on Coordinator instead of
    // Device.
    void CompleteSuspend(zx_status_t status);

    zx::channel take_client_remote() { return std::move(client_remote_); }

    const fbl::String& name() const { return name_; }
    const fbl::String& libname() const { return libname_; }
    const fbl::String& args() const { return args_; }

    Coordinator* coordinator;
    uint32_t flags = 0;

    // The backoff between each driver retry. This grows exponentially.
    zx::duration backoff = zx::msec(250);
    // The number of retries left for the driver.
    uint32_t retries = 4;
    Devnode* self = nullptr;
    Devnode* link = nullptr;

    // TODO(teisenbe): We probably want more states.  For example, the DEAD flag
    // should probably move in to here.
    enum class State {
        kActive,
        kSuspended,
    };

    State state() const { return state_; }
private:
    zx_status_t HandleRead();

    const fbl::String name_;
    const fbl::String libname_;
    const fbl::String args_;

    fbl::RefPtr<Device> parent_;
    const uint32_t protocol_id_;

    fbl::RefPtr<Device> proxy_;

    fbl::Array<const zx_device_prop_t> props_;
    // If the device has a topological property in |props|, this points to it.
    const zx_device_prop_t* topo_prop_ = nullptr;

    async::TaskClosure publish_task_;

    // listnode for this device in its parent's list-of-children
    fbl::DoublyLinkedListNodeState<Device*> node_;

    // List of all child devices of this device, except for composite devices.
    // Composite devices are excluded because their multiple-parent nature
    // precludes using the same intrusive nodes as single-parent devices.
    fbl::DoublyLinkedList<Device*, Node> children_;

    // Metadata entries associated to this device.
    fbl::DoublyLinkedList<fbl::unique_ptr<Metadata>, Metadata::Node> metadata_;

    // listnode for this device in the all devices list
    fbl::DoublyLinkedListNodeState<Device*> all_devices_node_;

    // listnode for this device in its devhost's list-of-devices
    fbl::DoublyLinkedListNodeState<Device*> devhost_node_;

    // - If this device is part of a composite device, this is inhabited by
    //   CompositeDeviceComponent* and it points to the component that matched it.
    //   Note that this is only set on the device that matched the component, not
    //   the "component device" added by the component driver.
    // - If this device is a composite device, this is inhabited by
    //   CompositeDevice* and it points to the composite that describes it.
    // - Otherwise, it is inhabited by UnassociatedWithComposite
    struct UnassociatedWithComposite {};
    std::variant<UnassociatedWithComposite, CompositeDeviceComponent*, CompositeDevice*>
            composite_;

    Devhost* host_ = nullptr;
    // The id of this device from the perspective of the devhost.  This can be
    // used to communicate with the devhost about this device.
    uint64_t local_id_ = 0;

    // The current state of the device
    State state_ = State::kActive;

    // If a suspend is in-progress, this task represents it.
    fbl::RefPtr<SuspendTask> active_suspend_;
    // If a suspend is in-progress, this completion will be invoked when it is
    // completed.  It will likely mark |active_suspend_| as completed and clear
    // it.
    SuspendCompletion suspend_completion_;

    // For attaching as an open connection to the proxy device,
    // or once the device becomes visible.
    zx::channel client_remote_;
};

} // namespace devmgr
