// Copyright 2018 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/protocol/display/controller.h>
#include <ddktl/device.h>
#include <fbl/intrusive_double_list.h>
#include <fbl/intrusive_hash_table.h>
#include <fbl/unique_ptr.h>
#include <fbl/vector.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async/cpp/receiver.h>
#include <lib/async/cpp/task.h>
#include <lib/async/cpp/wait.h>
#include <lib/fidl/cpp/builder.h>
#include <lib/zx/channel.h>
#include <lib/zx/event.h>
#include <zircon/device/display-controller.h>
#include <zircon/listnode.h>

#include <map>

#include "controller.h"
#include "fence.h"
#include "fuchsia/hardware/display/c/fidl.h"
#include "id-map.h"
#include "image.h"

namespace display {

class Layer;
class Client;

typedef struct layer_node : public fbl::SinglyLinkedListable<layer_node*> {
    Layer* layer;
} layer_node_t;

// Almost-POD used by Client to manage layer state. Public state is used by Controller.
class Layer : public IdMappable<fbl::unique_ptr<Layer>> {
public:
    fbl::RefPtr<Image> current_image() const { return displayed_image_; }
    uint32_t z_order() const { return current_layer_.z_index; }
    bool is_skipped() const { return is_skipped_; }

private:
    layer_t pending_layer_;
    layer_t current_layer_;
    // flag indicating that there are changes in pending_layer that
    // need to be applied to current_layer.
    bool config_change_;

    // Event ids passed to SetLayerImage which haven't been applied yet.
    uint64_t pending_wait_event_id_;
    uint64_t pending_signal_event_id_;

    // The image given to SetLayerImage which hasn't been applied yet.
    fbl::RefPtr<Image> pending_image_;

    // Image which are waiting to be displayed
    list_node_t waiting_images_ = LIST_INITIAL_VALUE(waiting_images_);
    // The image which has most recently been sent to the display controller impl
    fbl::RefPtr<Image> displayed_image_;

    // Counters used for keeping track of when the layer's images need to be dropped.
    uint64_t pending_image_config_gen_ = 0;
    uint64_t current_image_config_gen_ = 0;

    int32_t pending_cursor_x_;
    int32_t pending_cursor_y_;
    int32_t current_cursor_x_;
    int32_t current_cursor_y_;

    // Storage for a color layer's color data bytes.
    uint8_t pending_color_bytes_[4];
    uint8_t current_color_bytes_[4];

    layer_node_t pending_node_;
    layer_node_t current_node_;

    // The display this layer was most recently displayed on
    uint64_t current_display_id_;

    bool is_skipped_;

    friend Client;
};

// Almost-POD used by Client to manage display configuration. Public state is used by Controller.
class DisplayConfig : public IdMappable<fbl::unique_ptr<DisplayConfig>> {
public:
    bool apply_layer_change() {
        bool ret = pending_apply_layer_change_;
        pending_apply_layer_change_ = false;
        return ret;
    }

    uint32_t vsync_layer_count() const { return vsync_layer_count_; }
    const display_config_t* current_config() const { return &current_; }
    const fbl::SinglyLinkedList<layer_node_t*>& get_current_layers() const {
        return current_layers_;
    }

private:
    display_config_t current_;
    display_config_t pending_;

    bool pending_layer_change_;
    bool pending_apply_layer_change_;
    fbl::SinglyLinkedList<layer_node_t*> pending_layers_;
    fbl::SinglyLinkedList<layer_node_t*> current_layers_;

    fbl::Array<zx_pixel_format_t> pixel_formats_;
    fbl::Array<cursor_info_t> cursor_infos_;

    uint32_t vsync_layer_count_;
    bool display_config_change_ = false;

    friend Client;
    friend ClientProxy;
};

// The Client class manages all state associated with an open display client
// connection. Over than initialization, all methods of this class execute on
// on the controller's looper, so no synchronization is necessary.
class Client : private FenceCallback {
public:
    Client(Controller* controller, ClientProxy* proxy, bool is_vc);

    // This is used for testing
    Client(Controller* controller, ClientProxy* proxy, bool is_vc, zx_handle_t server_handle);

    ~Client();
    zx_status_t Init(zx_handle_t server_handle);

    void OnDisplaysChanged(const uint64_t* displays_added,
                           size_t added_count,
                           const uint64_t* displays_removed,
                          size_t removed_count);
    void SetOwnership(bool is_owner);
    void ApplyConfig();

    void OnFenceFired(FenceReference* fence) override;
    void OnRefForFenceDead(Fence* fence) override;

    void TearDown();

    // This is used for testing
    void TearDownTest();

    bool IsValid() { return server_handle_ != ZX_HANDLE_INVALID; }
private:
    void HandleImportVmoImage(const fuchsia_hardware_display_ControllerImportVmoImageRequest* req,
                              fidl::Builder* resp_builder, const fidl_type_t** resp_table);
    void HandleImportImage(const fuchsia_hardware_display_ControllerImportImageRequest* req,
                           fidl::Builder* resp_builder, const fidl_type_t** resp_table);
    void HandleReleaseImage(const fuchsia_hardware_display_ControllerReleaseImageRequest* req,
                            fidl::Builder* resp_builder, const fidl_type_t** resp_table);
    void HandleImportEvent(const fuchsia_hardware_display_ControllerImportEventRequest* req,
                           fidl::Builder* resp_builder, const fidl_type_t** resp_table);
    void HandleReleaseEvent(const fuchsia_hardware_display_ControllerReleaseEventRequest* req,
                            fidl::Builder* resp_builder, const fidl_type_t** resp_table);
    void HandleCreateLayer(const fuchsia_hardware_display_ControllerCreateLayerRequest* req,
                           fidl::Builder* resp_builder, const fidl_type_t** resp_table);
    void HandleDestroyLayer(const fuchsia_hardware_display_ControllerDestroyLayerRequest* req,
                            fidl::Builder* resp_builder, const fidl_type_t** resp_table);
    void HandleSetDisplayMode(const fuchsia_hardware_display_ControllerSetDisplayModeRequest* req,
                              fidl::Builder* resp_builder, const fidl_type_t** resp_table);
    void HandleSetDisplayColorConversion(
        const fuchsia_hardware_display_ControllerSetDisplayColorConversionRequest* req,
        fidl::Builder* resp_builder, const fidl_type_t** resp_table);
    void
    HandleSetDisplayLayers(const fuchsia_hardware_display_ControllerSetDisplayLayersRequest* req,
                           fidl::Builder* resp_builder, const fidl_type_t** resp_table);
    void HandleSetLayerPrimaryConfig(
        const fuchsia_hardware_display_ControllerSetLayerPrimaryConfigRequest* req,
        fidl::Builder* resp_builder, const fidl_type_t** resp_table);
    void HandleSetLayerPrimaryPosition(
        const fuchsia_hardware_display_ControllerSetLayerPrimaryPositionRequest* req,
        fidl::Builder* resp_builder, const fidl_type_t** resp_table);
    void HandleSetLayerPrimaryAlpha(
        const fuchsia_hardware_display_ControllerSetLayerPrimaryAlphaRequest* req,
        fidl::Builder* resp_builder, const fidl_type_t** resp_table);
    void HandleSetLayerCursorConfig(
        const fuchsia_hardware_display_ControllerSetLayerCursorConfigRequest* req,
        fidl::Builder* resp_builder, const fidl_type_t** resp_table);
    void HandleSetLayerCursorPosition(
        const fuchsia_hardware_display_ControllerSetLayerCursorPositionRequest* req,
        fidl::Builder* resp_builder, const fidl_type_t** resp_table);
    void HandleSetLayerColorConfig(
        const fuchsia_hardware_display_ControllerSetLayerColorConfigRequest* req,
        fidl::Builder* resp_builder, const fidl_type_t** resp_table);
    void HandleSetLayerImage(const fuchsia_hardware_display_ControllerSetLayerImageRequest* req,
                             fidl::Builder* resp_builder, const fidl_type_t** resp_table);
    void HandleCheckConfig(const fuchsia_hardware_display_ControllerCheckConfigRequest* req,
                           fidl::Builder* resp_builder, const fidl_type_t** resp_table);
    void HandleApplyConfig(const fuchsia_hardware_display_ControllerApplyConfigRequest* req,
                           fidl::Builder* resp_builder, const fidl_type_t** resp_table);
    void HandleEnableVsync(const fuchsia_hardware_display_ControllerEnableVsyncRequest* req,
                           fidl::Builder* resp_builder, const fidl_type_t** resp_table);
    void HandleSetVirtconMode(const fuchsia_hardware_display_ControllerSetVirtconModeRequest* req,
                              fidl::Builder* resp_builder, const fidl_type_t** resp_table);
    void HandleComputeLinearImageStride(
        const fuchsia_hardware_display_ControllerComputeLinearImageStrideRequest* req,
        fidl::Builder* resp_builder, const fidl_type_t** resp_table);
    void HandleAllocateVmo(const fuchsia_hardware_display_ControllerAllocateVmoRequest* req,
                           fidl::Builder* resp_builder, zx_handle_t* handle_out,
                           bool* has_handle_out, const fidl_type_t** resp_table);
    void HandleGetSingleBufferFramebuffer(
        const fuchsia_hardware_display_ControllerGetSingleBufferFramebufferRequest* req,
        fidl::Builder* resp_builder, zx_handle_t* handle_out, bool* has_handle_out,
        const fidl_type_t** resp_table);
    void HandleImportBufferCollection(
        const fuchsia_hardware_display_ControllerImportBufferCollectionRequest* req,
        fidl::Builder* resp_builder, const fidl_type_t** resp_table);
    void HandleSetBufferCollectionConstraints(
        const fuchsia_hardware_display_ControllerSetBufferCollectionConstraintsRequest* req,
        fidl::Builder* resp_builder, const fidl_type_t** resp_table);
    void HandleReleaseBufferCollection(
        const fuchsia_hardware_display_ControllerReleaseBufferCollectionRequest* req,
        fidl::Builder* resp_builder, const fidl_type_t** resp_table);

    // Cleans up layer state associated with an image. If image == nullptr, then
    // cleans up all image state. Return true if a current layer was modified.
    bool CleanUpImage(Image* image);

    Controller* controller_;
    ClientProxy* proxy_;
    bool is_vc_;
    uint64_t console_fb_display_id_ = -1;

    zx_handle_t server_handle_;
    uint64_t next_image_id_ = 1; // Only INVALID_ID == 0 is invalid

    Image::Map images_;
    DisplayConfig::Map configs_;
    bool pending_config_valid_ = false;
    bool is_owner_ = false;
    // A counter for the number of times the client has successfully applied
    // a configuration. This does not account for changes due to waiting images.
    uint32_t client_apply_count_ = 0;

    zx::channel sysmem_allocator_;

    struct Collections {
        // Sent to the hardware driver.
        zx::channel driver;
        // If the VC is using this, |kernel| is the collection used for setting
        // it as kernel framebuffer.
        zx::channel kernel;
    };
    std::map<uint64_t, Collections> collection_map_;

    Fence::Map fences_ __TA_GUARDED(fence_mtx_);
    // Mutex held when creating or destroying fences.
    mtx_t fence_mtx_;

    Layer::Map layers_;
    uint64_t next_layer_id = 1;

    // TODO(stevensd): Delete this when client stop using SetDisplayImage
    uint64_t display_image_layer_ = INVALID_ID;

    void HandleControllerApi(async_dispatcher_t* dispatcher, async::WaitBase* self,
                             zx_status_t status, const zx_packet_signal_t* signal);
    async::WaitMethod<Client, &Client::HandleControllerApi> api_wait_{this};

    void NotifyDisplaysChanged(const int32_t* displays_added, uint32_t added_count,
                               const int32_t* displays_removed, uint32_t removed_count);
    bool CheckConfig(fidl::Builder* resp_builder);

    fbl::RefPtr<FenceReference> GetFence(uint64_t id);
};

// ClientProxy manages interactions between its Client instance and the ddk and the
// controller. Methods on this class are thread safe.
using ClientParent = ddk::Device<ClientProxy, ddk::Closable>;
class ClientProxy : public ClientParent {
public:
    ClientProxy(Controller* controller, bool is_vc);

    // This is used for testing
    ClientProxy(Controller* controller, bool is_vc, zx::channel server_channel);

    ~ClientProxy();
    zx_status_t Init(zx::channel server_channel);

    zx_status_t DdkClose(uint32_t flags);
    void DdkRelease();

    // Requires holding controller_->mtx() lock
    zx_status_t OnDisplayVsync(uint64_t display_id, zx_time_t timestamp,
                        uint64_t* image_ids, size_t count);
    void OnDisplaysChanged(const uint64_t* displays_added, size_t added_count,
                           const uint64_t* displays_removed, size_t removed_count);
    void SetOwnership(bool is_owner);
    void ReapplyConfig();

    // Requires holding controller_->mtx() lock
    void EnableVsync(bool enable) {
        ZX_DEBUG_ASSERT(mtx_trylock(controller_->mtx()) == thrd_busy);

        enable_vsync_ = enable;
    }
    void OnClientDead();
    void Close();

    // This is used for testing
    void CloseTest();

private:
    Controller* controller_;
    bool is_vc_;
    zx::channel server_channel_;
    Client handler_;
    bool enable_vsync_ = false;

    // This variable is used to limit the number of errors logged in case of channel oom error
    static constexpr uint32_t kChannelOomPrintFreq = 600; // 1 per 10 seconds (assuming 60fps)
    uint32_t chn_oom_print_freq_ = 0;
    uint64_t total_oom_errors_ = 0;
};

} // namespace display
