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

#include <lib/ddk/debug.h>
#include <lib/trace/event.h>
#include <zircon/errors.h>
#include <zircon/types.h>

#include <sstream>

#include <safemath/safe_conversions.h>

namespace camera {

OutputNode::OutputNode(async_dispatcher_t* dispatcher, BufferAttachments attachments)
    : ProcessNode(dispatcher, NodeType::kOutputStream, attachments, [](auto, auto) { abort(); }),
      dispatcher_(dispatcher),
      binding_(this) {
  binding_.set_error_handler([this](auto status) { callbacks_.disconnect(); });
}

fpromise::result<std::unique_ptr<OutputNode>, zx_status_t> OutputNode::Create(
    async_dispatcher_t* dispatcher, BufferAttachments attachments,
    fidl::InterfaceRequest<fuchsia::camera2::Stream> request, Callbacks callbacks) {
  ZX_ASSERT(request.is_valid());
  TRACE_DURATION("camera", "OutputNode::Create");
  auto node = std::make_unique<camera::OutputNode>(dispatcher, attachments);
  node->callbacks_ = std::move(callbacks);
  ZX_ASSERT(node->binding_.Bind(std::move(request), node->dispatcher_) == ZX_OK);
  return fpromise::ok(std::move(node));
}

void OutputNode::ProcessFrame(FrameToken token, frame_metadata_t metadata) {
  TRACE_DURATION("camera", "OutputNode::ProcessFrame", "buffer_index", *token);
  if (!started_) {
    return;  // ~token
  }

  frame_count_++;
  if (frame_count_ % kFrameCountHeartbeatInterval == 0) {
    zxlogf(INFO, "Camera node %s has produced %u frames", GetLabel().c_str(), frame_count_);
  }

  // Throttle the rate of binding warning messages.
  // Once a connection is unbound, every frame from the camera can produce multiple
  // of these warnings - one per stream.
  if (!binding_.is_bound()) {
    binding_warnings_++;
    if (binding_warnings_ <= kBindingWarningsInitial ||
        binding_warnings_ % kBindingWarningsInterval == 0) {
      std::stringstream ss;
      ss << this << ": client disconnected? returning frame... (seen " << binding_warnings_
         << " times)";
      ss << "Camera node " << this << " client reconnected? delivering frame...";
      zxlogf(WARNING, "%s", ss.str().c_str());
    }
    return;  // ~token
  }

  if (binding_warnings_ > 0) {
    std::stringstream ss;
    ss << "Camera node " << this << " client reconnected? delivering frame...";
    zxlogf(INFO, "%s", ss.str().c_str());
    binding_warnings_ = 0;
  }

  TRACE_FLOW_BEGIN("camera", "camera_stream_on_frame_available", metadata.timestamp);
  client_tokens_.emplace(*token, token);
  fuchsia::camera2::FrameAvailableInfo frame_info{};
  frame_info.frame_status = fuchsia::camera2::FrameStatus::OK;
  frame_info.buffer_id = *token;
  frame_info.metadata.set_image_format_index(metadata.image_format_index);
  frame_info.metadata.set_timestamp(safemath::checked_cast<int64_t>(metadata.timestamp));
  frame_info.metadata.set_capture_timestamp(
      safemath::checked_cast<int64_t>(metadata.capture_timestamp));
  ZX_ASSERT(binding_.is_bound());
  binding_.events().OnFrameAvailable(std::move(frame_info));
}

void OutputNode::SetOutputFormat(uint32_t output_format_index, fit::closure callback) {
  TRACE_DURATION("camera", "OutputNode::SetOutputFormat", "format_index", output_format_index);
  callback();
}

void OutputNode::ShutdownImpl(fit::closure callback) {
  TRACE_DURATION("camera", "OutputNode::ShutdownImpl");
  client_tokens_.clear();
  callback();
}

void OutputNode::HwFrameReady(frame_available_info_t info) { abort(); }
void OutputNode::HwFrameResolutionChanged(frame_available_info_t info) { abort(); }
void OutputNode::HwTaskRemoved(task_remove_status_t status) { abort(); }

void OutputNode::Stop() {
  std::stringstream ss;
  ss << "Camera node " << this << " Stop()";
  zxlogf(INFO, "%s", ss.str().c_str());
  started_ = false;
}

void OutputNode::Start() {
  std::stringstream ss;
  ss << "Camera node " << this << " Start()";
  zxlogf(INFO, "%s", ss.str().c_str());
  started_ = true;
}

void OutputNode::ReleaseFrame(uint32_t buffer_id) {
  auto element = client_tokens_.extract(buffer_id);
  if (element.empty()) {
    zxlogf(INFO, "Client called ReleaseFrame on non-held buffer %u", buffer_id);
  }
}

void OutputNode::AcknowledgeFrameError() {
  zxlogf(ERROR, "Camera node %s not implemented", __PRETTY_FUNCTION__);
}

void OutputNode::SetRegionOfInterest(float x_min, float y_min, float x_max, float y_max,
                                     SetRegionOfInterestCallback callback) {
  TRACE_DURATION("camera", "OutputNode::SetRegionOfInterest");
  callbacks_.set_region_of_interest(x_min, y_min, x_max, y_max, std::move(callback));
}

void OutputNode::SetImageFormat(uint32_t image_format_index, SetImageFormatCallback callback) {
  TRACE_DURATION("camera", "OutputNode::SetImageFormat");
  callbacks_.set_image_format(image_format_index, std::move(callback));
}

void OutputNode::GetImageFormats(GetImageFormatsCallback callback) {
  TRACE_DURATION("camera", "OutputNode::GetImageFormats");
  callbacks_.get_image_formats(std::move(callback));
}

void OutputNode::GetBuffers(GetBuffersCallback callback) {
  TRACE_DURATION("camera", "OutputNode::GetBuffers");
  callbacks_.get_buffers(std::move(callback));
}

}  // namespace camera
