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

#ifndef SRC_GRAPHICS_DISPLAY_TESTING_VIRTUAL_LAYER_H_
#define SRC_GRAPHICS_DISPLAY_TESTING_VIRTUAL_LAYER_H_

#include <fuchsia/hardware/display/llcpp/fidl.h>
#include <fuchsia/sysmem/llcpp/fidl.h>
#include <lib/zx/channel.h>
#include <zircon/types.h>

#include "display.h"
#include "image.h"

namespace testing {
namespace display {

typedef struct custom_layer {
  uint64_t id;
  bool active;

  bool done;

  ::llcpp::fuchsia::hardware::display::Frame src;
  ::llcpp::fuchsia::hardware::display::Frame dest;

  image_import_t import_info[2];
} custom_layer_t;

// A layer whose output can appear on multiple displays.
class VirtualLayer {
 public:
  typedef ::llcpp::fuchsia::hardware::display::Controller Controller;

  explicit VirtualLayer(Display* display);
  explicit VirtualLayer(const fbl::Vector<Display>& displays, bool tiled = true);

  virtual ~VirtualLayer() {}

  // Finish initializing the layer. All Set* methods should be called before this.
  virtual bool Init(Controller::SyncClient* dc) = 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(Controller::SyncClient* dc) = 0;

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

  virtual void* GetCurrentImageBuf() = 0;
  virtual size_t GetCurrentImageSize() = 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 ::llcpp::fuchsia::hardware::display::INVALID_DISP_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:
  custom_layer_t* CreateLayer(Controller::SyncClient* dc);
  void SetLayerImages(Controller::SyncClient* dc, bool alt_image);

  fbl::Vector<Display*> displays_;
  fbl::Vector<custom_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, bool mirrors = false);
  explicit PrimaryLayer(const fbl::Vector<Display>& displays, uint32_t fgcolor, uint32_t bgcolor,
                        bool mirrors = false);

  // 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; }
  void SetFormatModifier(uint64_t modifier) { modifier_ = modifier; }

  bool Init(Controller::SyncClient* dc) override;
  void StepLayout(int32_t frame_num) override;
  bool WaitForReady() override;
  void SendLayout(Controller::SyncClient* channel) override;
  void Render(int32_t frame_num) override;

  void* GetCurrentImageBuf() override;
  size_t GetCurrentImageSize() 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 ::llcpp::fuchsia::hardware::display::INVALID_DISP_ID;
  }

 private:
  void SetLayerPositions(Controller::SyncClient* dc);
  bool Wait(uint32_t idx);
  void InitImageDimens();

  uint32_t image_width_ = 0;
  uint32_t image_height_ = 0;
  uint32_t image_format_ = 0;
  bool override_colors_ = false;
  uint32_t fgcolor_;
  uint32_t bgcolor_;

  ::llcpp::fuchsia::hardware::display::Frame src_frame_ = {};
  ::llcpp::fuchsia::hardware::display::Frame dest_frame_ = {};
  typedef ::llcpp::fuchsia::hardware::display::Transform Transform;
  Transform rotation_ = 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;
  uint64_t modifier_ = ::llcpp::fuchsia::sysmem::FORMAT_MODIFIER_LINEAR;
  bool mirrors_ = 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(Controller::SyncClient* dc) override;
  void StepLayout(int32_t frame_num) override;
  void SendLayout(Controller::SyncClient* dc) override;

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

  void* GetCurrentImageBuf() override { return nullptr; }
  size_t GetCurrentImageSize() override { return 0; }

  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 ::llcpp::fuchsia::hardware::display::INVALID_DISP_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(Controller::SyncClient* dc) override;

  void SendLayout(Controller::SyncClient* dc) override {}
  void StepLayout(int32_t frame_num) override {}
  bool WaitForReady() override { return true; }
  void Render(int32_t frame_num) override {}
  void* GetCurrentImageBuf() override { return nullptr; }
  size_t GetCurrentImageSize() override { return 0; }
  uint64_t image_id(uint64_t display_id) const override {
    return ::llcpp::fuchsia::hardware::display::INVALID_DISP_ID;
  }
  virtual bool is_done() const override { return true; }
};

}  // namespace display
}  // namespace testing

#endif  // SRC_GRAPHICS_DISPLAY_TESTING_VIRTUAL_LAYER_H_
