// 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 <zircon/device/display-controller.h>
#include <zircon/types.h>
#include <lib/zx/channel.h>

#include "display.h"
#include "fuchsia/hardware/display/c/fidl.h"
#include "image.h"

typedef struct frame {
    uint32_t width;
    uint32_t height;
    uint32_t x_pos;
    uint32_t y_pos;
} frame_t;

typedef struct layer {
    uint64_t id;
    bool active;

    bool done;

    frame_t src;
    frame_t dest;

    image_import_t import_info[2];
} layer_t;

// A layer whose output can appear on multiple displays.
class VirtualLayer {
public:
    explicit VirtualLayer(Display* display);
    explicit VirtualLayer(const fbl::Vector<Display>& displays);

    virtual ~VirtualLayer() {}

    // Finish initializing the layer. All Set* methods should be called before this.
    virtual bool Init(zx_handle_t channel) = 0;

    // Steps the local layout state to frame_num.
    virtual void StepLayout(int32_t frame_num) = 0;

    // Waits for the display controller to be done with the previous version of this frame.
    virtual bool WaitForReady() = 0;

    // Sets the current layout to the display contorller.
    virtual void SendLayout(zx_handle_t channel) = 0;

    // Renders the current frame (and signals the fence if necessary).
    virtual void Render(int32_t frame_num) = 0;

    // Gets the display controller layer ID for usage on the given display.
    uint64_t id(uint64_t display_id) const {
        for (unsigned i = 0; i < displays_.size(); i++) {
            if (displays_[i]->id() == display_id && layers_[i].active) {
                return layers_[i].id;
            }
        }
        return INVALID_ID;
    }

    // Gets the ID of the image on the given display.
    virtual uint64_t image_id(uint64_t display_id) const = 0;

    void set_frame_done(uint64_t display_id) {
        for (unsigned i = 0; i < displays_.size(); i++) {
            if (displays_[i]->id() == display_id) {
                layers_[i].done = true;
            }
        }
    }

    virtual bool is_done() const {
        bool done = true;
        for (unsigned i = 0; i < displays_.size(); i++) {
            done &= !layers_[i].active || layers_[i].done;
        }
        return done;
    }

    void clear_done() {
        for (unsigned i = 0; i < displays_.size(); i++) {
            layers_[i].done = false;
        }
    }

protected:
    layer_t* CreateLayer(zx_handle_t dc_handle);
    void SetLayerImages(zx_handle_t handle, bool alt_image);

    fbl::Vector<Display*> displays_;
    fbl::Vector<layer_t> layers_;

    uint32_t width_;
    uint32_t height_;
};

class PrimaryLayer : public VirtualLayer {
public:
    explicit PrimaryLayer(Display* display);
    explicit PrimaryLayer(const fbl::Vector<Display>& displays);

    // Set* methods to configure the layer.
    void SetImageDimens(uint32_t width, uint32_t height) {
        image_width_ = width;
        image_height_ = height;

        src_frame_.width = width;
        src_frame_.height = height;
        dest_frame_.width = width;
        dest_frame_.height = height;
    }
    void SetSrcFrame(uint32_t width, uint32_t height) {
        src_frame_.width = width;
        src_frame_.height = height;
    }
    void SetDestFrame(uint32_t width, uint32_t height) {
        dest_frame_.width = width;
        dest_frame_.height = height;
    }
    void SetLayerFlipping(bool flip) { layer_flipping_ = flip; }
    void SetPanSrc(bool pan) { pan_src_ = pan; }
    void SetPanDest(bool pan) { pan_dest_ = pan; }
    void SetLayerToggle(bool toggle) { layer_toggle_ = toggle; }
    void SetRotates(bool rotates) { rotates_ = rotates; }
    void SetAlpha(bool enable, float val) {
        alpha_enable_ = enable;
        alpha_val_ = val;
    }
    void SetScaling(bool enable) {
        scaling_ = enable;
    }
    void SetImageFormat(uint32_t image_format) { image_format_ = image_format; }

    bool Init(zx_handle_t channel) override;
    void StepLayout(int32_t frame_num) override;
    bool WaitForReady() override;
    void SendLayout(zx_handle_t channel) override;
    void Render(int32_t frame_num) override;

    uint64_t image_id(uint64_t display_id) const override {
        for (unsigned i = 0; i < displays_.size(); i++) {
            if (displays_[i]->id() == display_id && layers_[i].active) {
                return layers_[i].import_info[alt_image_].id;
            }
        }
        return INVALID_ID;
    }

private:
    void SetLayerPositions(zx_handle_t handle);
    bool Wait(uint32_t idx);
    void InitImageDimens();

    uint32_t image_width_ = 0;
    uint32_t image_height_ = 0;
    uint32_t image_format_ = 0;
    frame_t src_frame_ = {};
    frame_t dest_frame_ = {};
    uint8_t rotation_ = fuchsia_hardware_display_Transform_IDENTITY;
    bool layer_flipping_ = false;
    bool pan_src_ = false;
    bool pan_dest_ = false;
    bool layer_toggle_ = false;
    bool rotates_ = false;
    bool alpha_enable_ = false;
    float alpha_val_ = 0.f;
    bool scaling_ = false;

    bool alt_image_ = false;
    Image* images_[2];
};

class CursorLayer : public VirtualLayer {
public:
    explicit CursorLayer(Display* display);
    explicit CursorLayer(const fbl::Vector<Display>& displays);

    bool Init(zx_handle_t channel) override;
    void StepLayout(int32_t frame_num) override;
    void SendLayout(zx_handle_t channel) override;

    bool WaitForReady() override { return true; }
    void Render(int32_t frame_num) override {}

    uint64_t image_id(uint64_t display_id) const override {
        for (unsigned i = 0; i < displays_.size(); i++) {
            if (displays_[i]->id() == display_id && layers_[i].active) {
                return layers_[i].import_info[0].id;
            }
        }
        return INVALID_ID;
    }


private:
    uint32_t x_pos_ = 0;
    uint32_t y_pos_ = 0;

    Image* image_;
};

class ColorLayer : public VirtualLayer {
public:
    explicit ColorLayer(Display* display);
    explicit ColorLayer(const fbl::Vector<Display>& displays);

    bool Init(zx_handle_t channel) override;

    void SendLayout(zx_handle_t channel) override {}
    void StepLayout(int32_t frame_num) override {}
    bool WaitForReady() override { return true; }
    void Render(int32_t frame_num) override {}
    uint64_t image_id(uint64_t display_id) const override { return INVALID_ID; }
    virtual bool is_done() const override { return true; }
};
