// 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);
  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
