// 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/input_node.h"

#include <lib/syslog/cpp/macros.h>
#include <zircon/errors.h>
#include <zircon/types.h>

#include <ddk/protocol/isp.h>
#include <ddk/trace/event.h>

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

namespace camera {

constexpr auto kTag = "camera_controller_input_node";

fit::result<std::unique_ptr<InputNode>, zx_status_t> InputNode::CreateInputNode(
    StreamCreationData* info, const ControllerMemoryAllocator& memory_allocator,
    async_dispatcher_t* dispatcher, const ddk::IspProtocolClient& isp) {
  uint8_t isp_stream_type;
  if (info->node.input_stream_type == fuchsia::camera2::CameraStreamType::FULL_RESOLUTION) {
    isp_stream_type = STREAM_TYPE_FULL_RESOLUTION;
  } else if (info->node.input_stream_type ==
             fuchsia::camera2::CameraStreamType::DOWNSCALED_RESOLUTION) {
    isp_stream_type = STREAM_TYPE_DOWNSCALED;
  } else {
    return fit::error(ZX_ERR_INVALID_ARGS);
  }

  auto result = camera::GetBuffers(memory_allocator, info->node, info, kTag);
  if (result.is_error()) {
    FX_PLOGST(ERROR, kTag, result.error()) << "Failed to get buffers";
    return fit::error(result.error());
  }
  auto buffers = std::move(result.value());

  // Use a BufferCollectionHelper to manage the conversion
  // between buffer collection representations.
  BufferCollectionHelper buffer_collection_helper(buffers);

  auto image_format = ConvertHlcppImageFormat2toCType(info->node.image_formats[0]);

  // Create Input Node
  auto processing_node =
      std::make_unique<camera::InputNode>(info, std::move(buffers), dispatcher, isp);
  if (!processing_node) {
    FX_LOGST(ERROR, kTag) << "Failed to create Input node";
    return fit::error(ZX_ERR_NO_MEMORY);
  }

  // Create stream with ISP
  auto isp_stream_protocol = std::make_unique<camera::IspStreamProtocol>();
  if (!isp_stream_protocol) {
    FX_LOGST(ERROR, kTag) << "Failed to create ISP stream protocol";
    return fit::error(ZX_ERR_INTERNAL);
  }

  auto status = isp.CreateOutputStream(
      buffer_collection_helper.GetC(), &image_format,
      reinterpret_cast<const frame_rate_t*>(&info->node.output_frame_rate), isp_stream_type,
      processing_node->isp_frame_callback(), isp_stream_protocol->protocol());
  if (status != ZX_OK) {
    FX_PLOGST(ERROR, kTag, status) << "Failed to create output stream on ISP";
    return fit::error(status);
  }

  // Update the input node with the ISP stream protocol
  processing_node->set_isp_stream_protocol(std::move(isp_stream_protocol));
  return fit::ok(std::move(processing_node));
}

void InputNode::OnReadyToProcess(const frame_available_info_t* info) {
  // Use the timestamp of the input as the capture time.
  auto modified = *info;
  modified.metadata.capture_timestamp = info->metadata.timestamp;
  OnFrameAvailable(&modified);
}

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

  UpdateFrameCounterForAllChildren();

  if (NeedToDropFrame()) {
    TRACE_INSTANT("camera", "drop_frame", TRACE_SCOPE_THREAD);
    isp_stream_protocol_->ReleaseFrame(info->buffer_id);
    return;
  }
  ProcessNode::OnFrameAvailable(info);
}

void InputNode::OnReleaseFrame(uint32_t buffer_index) {
  TRACE_DURATION("camera", "InputNode::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_) {
    isp_stream_protocol_->ReleaseFrame(buffer_index);
  }
}

void InputNode::OnStartStreaming() {
  enabled_ = true;
  isp_stream_protocol_->Start();
}

void InputNode::OnStopStreaming() {
  if (AllChildNodesDisabled()) {
    enabled_ = false;
    isp_stream_protocol_->Stop();
  }
}

void InputNode::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 ISP driver.
  shutdown_requested_ = true;

  isp_stream_shutdown_callback_t isp_stream_shutdown_cb = {
      .shutdown_complete =
          [](void* ctx, zx_status_t /*status*/) {
            auto* input_node = static_cast<decltype(this)>(ctx);
            input_node->node_callback_received_ = true;
            input_node->OnCallbackReceived();
          },
      .ctx = this,
  };

  zx_status_t status = isp_stream_protocol_->Shutdown(&isp_stream_shutdown_cb);
  if (status != ZX_OK) {
    FX_PLOGST(ERROR, kTag, status) << "Failure during stream shutdown";
    return;
  }

  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.
  if (child_nodes().empty()) {
    // If an incomplete graph is shut down, invoke the completion directly.
    child_shutdown_completion_callback();
  } else {
    // Otherwise, propagate the shutdown command and completion to the next child.
    child_nodes().at(0)->OnShutdown(child_shutdown_completion_callback);
  }
}

}  // namespace camera
