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

#include "src/ui/bin/root_presenter/color_transform_handler.h"

#include <lib/sys/cpp/component_context.h>
#include <lib/syslog/cpp/macros.h>
#include <zircon/status.h>

#include "src/ui/bin/root_presenter/safe_presenter.h"

namespace root_presenter {

const std::array<float, 3> kZero = {0, 0, 0};

ColorTransformHandler::ColorTransformHandler(sys::ComponentContext* component_context,
                                             scenic::ResourceId compositor_id,
                                             scenic::Session* session,
                                             SafePresenter* safe_presenter)
    : ColorTransformHandler(component_context, compositor_id, session, safe_presenter,
                            ColorTransformState()) {}

ColorTransformHandler::ColorTransformHandler(sys::ComponentContext* component_context,
                                             scenic::ResourceId compositor_id,
                                             scenic::Session* session,
                                             SafePresenter* safe_presenter,
                                             ColorTransformState state)
    : component_context_(component_context),
      session_(session),
      safe_presenter_(safe_presenter),
      compositor_id_(compositor_id),
      color_transform_handler_bindings_(this),
      color_transform_state_(state) {
  FX_DCHECK(component_context_);
  FX_DCHECK(session_);
  FX_DCHECK(safe_presenter_);
  component_context->svc()->Connect(color_transform_manager_.NewRequest());
  color_transform_manager_.set_error_handler([](zx_status_t status) {
    FX_LOGS(WARNING) << "Unable to connect to ColorTransformManager: "
                     << zx_status_get_string(status);
  });
  fidl::InterfaceHandle<fuchsia::accessibility::ColorTransformHandler> handle;
  color_transform_handler_bindings_.Bind(handle.NewRequest());
  color_transform_manager_->RegisterColorTransformHandler(std::move(handle));
  component_context->outgoing()->AddPublicService(color_adjustment_bindings_.GetHandler(this));
  component_context->outgoing()->AddPublicService(display_backlight_bindings_.GetHandler(this));
}

ColorTransformHandler::~ColorTransformHandler() {
  component_context_->outgoing()
      ->RemovePublicService<fuchsia::ui::brightness::ColorAdjustmentHandler>();
  component_context_->outgoing()->RemovePublicService<fuchsia::ui::policy::DisplayBacklight>();
}

void ColorTransformHandler::SetColorTransformConfiguration(
    fuchsia::accessibility::ColorTransformConfiguration configuration,
    SetColorTransformConfigurationCallback callback) {
  if (!configuration.has_color_adjustment_matrix()) {
    FX_LOGS(ERROR) << "ColorTransformConfiguration missing color adjustment matrix.";
    return;
  }
  if (!configuration.has_color_adjustment_pre_offset()) {
    FX_LOGS(ERROR) << "ColorTransformConfiguration missing color adjustment pre offset vector.";
    return;
  }
  if (!configuration.has_color_adjustment_post_offset()) {
    FX_LOGS(ERROR) << "ColorTransformConfiguration missing color adjustment post offset vector.";
    return;
  }
  SetScenicColorConversion(configuration.color_adjustment_matrix(),
                           configuration.color_adjustment_pre_offset(),
                           configuration.color_adjustment_post_offset());
  color_transform_state_.Update(std::move(configuration));
}

void ColorTransformHandler::SetColorAdjustment(
    fuchsia::ui::brightness::ColorAdjustmentTable color_adjustment_table) {
  if (color_transform_state_.IsActive()) {
    FX_LOGS(INFO) << "Ignoring SetColorAdjustment because color correction is currently active.";
    return;
  }

  if (!color_adjustment_table.has_matrix()) {
    FX_LOGS(INFO) << "Ignoring SetColorAdjustment because matrix is empty";
    return;
  }

  SetScenicColorConversion(color_adjustment_table.matrix(), /* preoffsets */ kZero,
                           /* postoffsets */ kZero);
}

void ColorTransformHandler::SetMinimumRgb(uint8_t minimum_rgb, SetMinimumRgbCallback callback) {
  // Init Scenic command
  fuchsia::ui::gfx::SetDisplayMinimumRgbCmdHACK display_minimum_rgb_cmd;
  display_minimum_rgb_cmd.min_value = minimum_rgb;

  // Create and enqueue scenic color adjustment cmd.
  fuchsia::ui::gfx::Command color_adjustment_cmd;
  color_adjustment_cmd.set_set_display_minimum_rgb(std::move(display_minimum_rgb_cmd));
  session_->Enqueue(std::move(color_adjustment_cmd));

  // Present with callback.
  safe_presenter_->QueuePresent(std::move(callback));
}

void ColorTransformHandler::SetScenicColorConversion(
    const std::array<float, 9> color_transform_matrix,
    const std::array<float, 3> color_transform_pre_offsets,
    const std::array<float, 3> color_transform_post_offsets) {
  // Do nothing if the values are the same as before.
  if (color_transform_values_initialized_ &&
      prev_color_transform_matrix_ == color_transform_matrix &&
      prev_color_transform_pre_offsets_ == color_transform_pre_offsets &&
      prev_color_transform_post_offsets_ == color_transform_post_offsets)
    return;

  color_transform_values_initialized_ = true;
  prev_color_transform_matrix_ = color_transform_matrix;
  prev_color_transform_pre_offsets_ = color_transform_pre_offsets;
  prev_color_transform_post_offsets_ = color_transform_post_offsets;

  // Create scenic color adjustment cmd.
  fuchsia::ui::gfx::Command color_adjustment_cmd;
  fuchsia::ui::gfx::SetDisplayColorConversionCmdHACK display_color_conversion_cmd;
  InitColorConversionCmd(&display_color_conversion_cmd, color_transform_matrix,
                         color_transform_pre_offsets, color_transform_post_offsets);
  // Call scenic to apply color adjustment.
  color_adjustment_cmd.set_set_display_color_conversion(std::move(display_color_conversion_cmd));
  session_->Enqueue(std::move(color_adjustment_cmd));

  safe_presenter_->QueuePresent([] {});
}

void ColorTransformHandler::InitColorConversionCmd(
    fuchsia::ui::gfx::SetDisplayColorConversionCmdHACK* display_color_conversion_cmd,
    const std::array<float, 9> color_transform_matrix,
    const std::array<float, 3> color_transform_pre_offsets,
    const std::array<float, 3> color_transform_post_offsets) {
  display_color_conversion_cmd->compositor_id = compositor_id_;
  display_color_conversion_cmd->preoffsets = color_transform_pre_offsets;
  display_color_conversion_cmd->matrix = color_transform_matrix;
  display_color_conversion_cmd->postoffsets = color_transform_post_offsets;
}

}  // namespace root_presenter
