// 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/camera/drivers/controller/gdc_node.h"

#include <lib/fit/defer.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/trace/event.h>
#include <zircon/errors.h>
#include <zircon/types.h>

#include <safemath/safe_conversions.h>

#include "src/camera/drivers/controller/graph_utils.h"
#include "src/camera/drivers/controller/stream_pipeline_info.h"
#include "src/camera/lib/format_conversion/buffer_collection_helper.h"
#include "src/devices/lib/sysmem/sysmem.h"

namespace camera {

constexpr auto kTag = "camera_controller_gdc_node";

fit::result<gdc_config_info, zx_status_t> LoadGdcConfiguration(
    zx_device_t* device, ProductConfig& product_config, const camera::GdcConfig& config_type) {
  if (config_type == GdcConfig::INVALID) {
    FX_LOGST(DEBUG, kTag) << "Invalid GDC configuration type";
    return fit::error(ZX_ERR_INVALID_ARGS);
  }

  gdc_config_info info;
  size_t size;
  auto status =
      load_firmware(device, product_config.GetGdcConfigFile(config_type), &info.config_vmo, &size);
  if (status != ZX_OK || size == 0) {
    FX_PLOGST(ERROR, kTag, status) << "Failed to load the GDC firmware";
    return fit::error(status);
  }
  info.size = safemath::checked_cast<uint32_t>(size);
  return fit::ok(info);
}

void OnGdcFrameAvailable(void* ctx, const frame_available_info_t* info) {
  auto nonce = TRACE_NONCE();
  TRACE_DURATION("camera", "OnGdcFrameAvailable");
  TRACE_FLOW_BEGIN("camera", "post_gdc_frame_available", nonce);
  // This method is invoked by the GDC in its own thread,
  // so the event must be marshalled to the
  // controller's thread.
  auto* gdc_node = static_cast<GdcNode*>(ctx);
  gdc_node->RunOnMainThread([gdc_node, nonce, info = *info]() {
    TRACE_DURATION("camera", "OnGdcFrameAvailable.task");
    TRACE_FLOW_END("camera", "post_gdc_frame_available", nonce);
    gdc_node->OnFrameAvailable(&info);
  });
}

void OnGdcResChange(void* ctx, const frame_available_info_t* info) {
  static_cast<camera::ProcessNode*>(ctx)->OnResolutionChanged(info);
}

fit::result<ProcessNode*, zx_status_t> GdcNode::CreateGdcNode(
    const ControllerMemoryAllocator& memory_allocator, async_dispatcher_t* dispatcher,
    zx_device_t* device, const ddk::GdcProtocolClient& gdc, StreamCreationData* info,
    ProcessNode* parent_node, const InternalConfigNode& internal_gdc_node) {
  auto& input_buffers_hlcpp = parent_node->output_buffer_collection();
  auto result = GetBuffers(memory_allocator, internal_gdc_node, info, kTag);
  if (result.is_error()) {
    FX_LOGST(ERROR, kTag) << "Failed to get buffers";
    return fit::error(result.error());
  }

  auto output_buffers_hlcpp = std::move(result.value());

  BufferCollectionHelper output_buffer_collection_helper(output_buffers_hlcpp);
  BufferCollectionHelper input_buffer_collection_helper(input_buffers_hlcpp);

  // Convert the formats to C type
  std::vector<image_format_2_t> output_image_formats_c;
  for (const auto& format : internal_gdc_node.image_formats) {
    image_format_2_t value;
    auto original = GetImageFormatFromBufferCollection(*output_buffer_collection_helper.GetC(),
                                                       format.coded_width, format.coded_height);
    sysmem::image_format_2_banjo_from_fidl(original, value);
    output_image_formats_c.push_back(value);
  }

  // GDC only supports one input format and multiple output format at the
  // moment. So we take the first format from the previous node.
  // All existing usecases we support have only 1 format going into GDC.
  auto input_image_formats_c = GetImageFormatFromBufferCollection(
      *input_buffer_collection_helper.GetC(), parent_node->output_image_formats()[0].coded_width,
      parent_node->output_image_formats()[0].coded_height);

  // Get the GDC configurations loaded
  auto product_config = ProductConfig::Create();
  std::vector<gdc_config_info> config_vmos_info;
  for (const auto& config : internal_gdc_node.gdc_info.config_type) {
    auto gdc_config = LoadGdcConfiguration(device, *product_config, config);
    if (gdc_config.is_error()) {
      FX_LOGST(ERROR, kTag) << "Failed to load GDC configuration";
      return fit::error(gdc_config.error());
    }
    config_vmos_info.push_back(gdc_config.value());
  }

  auto cleanup = fit::defer([config_vmos_info]() {
    for (auto info : config_vmos_info) {
      ZX_ASSERT_MSG(ZX_OK == zx_handle_close(info.config_vmo), "Failed to free up Config VMOs");
    }
  });

  // Create GDC Node
  auto gdc_node = std::make_unique<camera::GdcNode>(dispatcher, gdc, parent_node, internal_gdc_node,
                                                    std::move(output_buffers_hlcpp),
                                                    info->stream_type(), info->image_format_index);
  if (!gdc_node) {
    FX_LOGST(ERROR, kTag) << "Failed to create GDC node";
    return fit::error(ZX_ERR_NO_MEMORY);
  }

  // Initialize the GDC to get a unique task index
  uint32_t gdc_task_index;
  buffer_collection_info_2 temp_input_collection, temp_output_collection;
  image_format_2_t temp_image_format;
  sysmem::buffer_collection_info_2_banjo_from_fidl(*input_buffer_collection_helper.GetC(),
                                                   temp_input_collection);
  sysmem::buffer_collection_info_2_banjo_from_fidl(*output_buffer_collection_helper.GetC(),
                                                   temp_output_collection);
  sysmem::image_format_2_banjo_from_fidl(input_image_formats_c, temp_image_format);
  auto status = gdc.InitTask(
      &temp_input_collection, &temp_output_collection, &temp_image_format,
      output_image_formats_c.data(), output_image_formats_c.size(), info->image_format_index,
      config_vmos_info.data(), config_vmos_info.size(), gdc_node->frame_callback(),
      gdc_node->res_callback(), gdc_node->remove_task_callback(), &gdc_task_index);
  if (status != ZX_OK) {
    FX_PLOGST(ERROR, kTag, status) << "Failed to initialize GDC";
    return fit::error(status);
  }

  gdc_node->set_task_index(gdc_task_index);

  // Add child node.
  auto return_value = fit::ok(gdc_node.get());
  parent_node->AddChildNodeInfo(std::move(gdc_node));
  return return_value;
}

void GdcNode::OnFrameAvailable(const frame_available_info_t* info) {
  ZX_ASSERT(thread_checker_.is_thread_valid());
  TRACE_DURATION("camera", "GdcNode::OnFrameAvailable", "buffer_index", info->buffer_id);
  if (shutdown_requested_ || info->frame_status != FRAME_STATUS_OK) {
    return;
  }

  UpdateFrameCounterForAllChildren();

  if (NeedToDropFrame()) {
    parent_node_->OnReleaseFrame(info->metadata.input_buffer_index);
    gdc_.ReleaseFrame(task_index_, info->buffer_id);
    return;
  }
  // Free up parent's frame.
  parent_node_->OnReleaseFrame(info->metadata.input_buffer_index);
  ProcessNode::OnFrameAvailable(info);
}

void GdcNode::OnReleaseFrame(uint32_t buffer_index) {
  TRACE_DURATION("camera", "GdcNode::OnReleaseFrame", "buffer_index", buffer_index);
  fbl::AutoLock al(&in_use_buffer_lock_);
  ZX_ASSERT(buffer_index < in_use_buffer_count_.size());
  in_use_buffer_count_[buffer_index]--;
  if (in_use_buffer_count_[buffer_index] != 0) {
    return;
  }
  if (!shutdown_requested_) {
    gdc_.ReleaseFrame(task_index_, buffer_index);
  }
}

void GdcNode::OnReadyToProcess(const frame_available_info_t* info) {
  auto nonce = TRACE_NONCE();
  TRACE_DURATION("camera", "GdcNode::OnReadyToProcess");
  TRACE_FLOW_BEGIN("camera", "post_process_frame", nonce);
  async::PostTask(dispatcher_, [this, nonce, buffer_index = info->buffer_id,
                                capture_timestamp = info->metadata.capture_timestamp]() {
    TRACE_DURATION("camera", "GdcNode::OnReadyToProcess.task", "buffer_index", buffer_index);
    TRACE_FLOW_END("camera", "post_process_frame", nonce);
    if (enabled_) {
      ZX_ASSERT(ZX_OK == gdc_.ProcessFrame(task_index_, buffer_index, capture_timestamp));
    } else {
      // Since streaming is disabled the incoming frame is released
      // so it gets added back to the pool.
      parent_node_->OnReleaseFrame(buffer_index);
    }
  });
}

void GdcNode::OnTaskRemoved(zx_status_t status) {
  ZX_ASSERT(status == ZX_OK);
  async::PostTask(dispatcher_, [this]() {
    node_callback_received_ = true;
    OnCallbackReceived();
  });
}

void GdcNode::OnShutdown(fit::function<void(void)> shutdown_callback) {
  shutdown_callback_ = std::move(shutdown_callback);

  // After a shutdown request has been made,
  // no other calls should be made to the GDC driver.
  shutdown_requested_ = true;

  // Request GDC to shutdown.
  gdc_.RemoveTask(task_index_);

  auto child_shutdown_completion_callback = [this]() {
    child_node_callback_received_ = true;
    OnCallbackReceived();
  };

  ZX_ASSERT_MSG(configured_streams().size() == 1,
                "Cannot shutdown a stream which supports multiple streams");

  // Forward the shutdown request to child node.
  child_nodes().at(0)->OnShutdown(child_shutdown_completion_callback);
}

void GdcNode::OnResolutionChangeRequest(uint32_t output_format_index) {
  if (enabled_) {
    TRACE_DURATION("camera", "GdcNode::OnResolutionChangeRequest", "index", output_format_index);
    gdc_.SetOutputResolution(task_index_, output_format_index);
    set_current_image_format_index(output_format_index);
  }
}
}  // namespace camera
