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

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

#include <utility>

#include <fbl/auto_call.h>

#include "src/camera/drivers/controller/graph_utils.h"
#include "src/camera/drivers/controller/processing_node.h"

namespace camera {

constexpr auto kTag = "camera_controller";

StreamImpl::StreamImpl(ProcessNode* output_node) : binding_(this), output_node_(*output_node) {}

zx_status_t StreamImpl::Attach(zx::channel channel, fit::function<void(void)> disconnect_handler) {
  FX_DCHECK(!binding_.is_bound());
  disconnect_handler_ = std::move(disconnect_handler);
  binding_.set_error_handler([this](zx_status_t status) {
    Shutdown(status);
    disconnect_handler_();
  });

  zx_status_t status = binding_.Bind(std::move(channel));
  if (status != ZX_OK) {
    FX_PLOGST(ERROR, kTag, status);
    return status;
  }
  return ZX_OK;
}

void StreamImpl::FrameReady(const frame_available_info_t* info) {
  TRACE_DURATION("camera", "StreamImpl::FrameReady");
  TRACE_FLOW_BEGIN("camera", "camera_stream_on_frame_available", info->metadata.timestamp);
  ZX_ASSERT(thread_checker_.is_thread_valid());
  fuchsia::camera2::FrameAvailableInfo frame_info;
  frame_info.frame_status = fuchsia::camera2::FrameStatus::OK;
  frame_info.buffer_id = info->buffer_id;
  frame_info.metadata.set_image_format_index(info->metadata.image_format_index);
  frame_info.metadata.set_timestamp(info->metadata.timestamp);
  frame_info.metadata.set_capture_timestamp(info->metadata.capture_timestamp);
  ZX_ASSERT(binding_.is_bound());
  binding_.events().OnFrameAvailable(std::move(frame_info));
}

void StreamImpl::Shutdown(zx_status_t status) {
  // Close the connection if it's open.
  if (binding_.is_bound()) {
    binding_.Close(status);
  }

  // Stop streaming if its started
  if (started_) {
    Stop();
  }
}

void StreamImpl::Stop() {
  output_node_.OnStopStreaming();
  started_ = false;
}

void StreamImpl::Start() {
  output_node_.OnStartStreaming();
  started_ = true;
}

void StreamImpl::ReleaseFrame(uint32_t buffer_id) { output_node_.OnReleaseFrame(buffer_id); }

void StreamImpl::AcknowledgeFrameError() {
  FX_LOGST(ERROR, kTag) << __PRETTY_FUNCTION__ << " not implemented";
  Shutdown(ZX_ERR_UNAVAILABLE);
}

void StreamImpl::SetRegionOfInterest(float x_min, float y_min, float x_max, float y_max,
                                     SetRegionOfInterestCallback callback) {
  zx_status_t status = ZX_OK;
  auto cleanup = fbl::MakeAutoCall([&]() { callback(status); });

  auto stream_type = output_node_.configured_streams().at(0);
  auto* parent_node = output_node_.parent_node();
  while (parent_node) {
    if (parent_node->is_crop_region_supported(stream_type)) {
      status = parent_node->OnSetCropRect(x_min, y_min, x_max, y_max);
      break;
    }
    parent_node = parent_node->parent_node();
  }
  if (parent_node == nullptr) {
    status = ZX_ERR_NOT_SUPPORTED;
  }
}

void StreamImpl::SetImageFormat(uint32_t image_format_index, SetImageFormatCallback callback) {
  zx_status_t status = ZX_OK;
  auto cleanup = fbl::MakeAutoCall([&]() {
    if (status == ZX_OK) {
      output_node_.set_current_image_format_index(image_format_index);
    }
    callback(status);
  });

  auto& available_image_formats = output_node_.output_image_formats();
  if (image_format_index >= available_image_formats.size()) {
    status = ZX_ERR_INVALID_ARGS;
    return;
  }

  auto stream_type = output_node_.configured_streams().at(0);

  auto* parent_node = output_node_.parent_node();
  if (output_node_.current_image_format_index() != image_format_index) {
    while (parent_node) {
      if (parent_node->is_dynamic_resolution_supported(stream_type)) {
        parent_node->OnResolutionChangeRequest(image_format_index);
        break;
      }
      parent_node = parent_node->parent_node();
    }
    if (parent_node == nullptr) {
      status = ZX_ERR_INVALID_ARGS;
    }
  }
}

void StreamImpl::GetImageFormats(GetImageFormatsCallback callback) {
  auto& available_image_formats = output_node_.output_image_formats();
  callback({available_image_formats.begin(), available_image_formats.end()});
}

}  // namespace camera
