// Copyright 2020 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/bin/camera-gym/stream_cycler.h"

#include <lib/async-loop/default.h>
#include <lib/async/cpp/task.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/trace/event.h>
#include <zircon/types.h>

#include <sstream>

#include "src/camera/bin/camera-gym/moving_window.h"
#include "src/lib/fsl/handles/object_info.h"

namespace camera {

constexpr zx::duration kDemoTime = zx::msec(CONFIGURATION_CYCLE_TIME_MS);

// Ratio controls how often ROI is moved.
// (1 = every frame, 2 = every other frame, etc)
constexpr uint32_t kRegionOfInterestFramesPerMoveRatio = 1;

// Sets the error handler on the provided interface to log an error and abort the process.
template <class T>
static void SetAbortOnError(fidl::InterfacePtr<T>& p, std::string message) {
  p.set_error_handler([message](zx_status_t status) {
    // FATAL severity causes abort to be called.
    FX_PLOGS(FATAL, status) << message;
  });
}

StreamCycler::StreamCycler(async_dispatcher_t* dispatcher, bool manual_mode)
    : dispatcher_(dispatcher), manual_mode_(manual_mode) {
  SetAbortOnError(watcher_, "fuchsia.camera3.DeviceWatcher disconnected.");
  SetAbortOnError(allocator_, "fuchsia.sysmem.Allocator disconnected.");
  SetAbortOnError(device_, "fuchsia.camera3.Device disconnected.");
}

StreamCycler::~StreamCycler() = default;

fit::result<std::unique_ptr<StreamCycler>, zx_status_t> StreamCycler::Create(
    fuchsia::camera3::DeviceWatcherHandle watcher, fuchsia::sysmem::AllocatorHandle allocator,
    async_dispatcher_t* dispatcher, bool manual_mode) {
  auto cycler = std::unique_ptr<StreamCycler>(new StreamCycler(dispatcher, manual_mode));

  zx_status_t status = cycler->watcher_.Bind(std::move(watcher), dispatcher);
  if (status != ZX_OK) {
    FX_PLOGS(ERROR, status);
    return fit::error(status);
  }

  status = cycler->allocator_.Bind(std::move(allocator), dispatcher);
  if (status != ZX_OK) {
    FX_PLOGS(ERROR, status);
    return fit::error(status);
  }

  cycler->watcher_->WatchDevices(
      fit::bind_member(cycler.get(), &StreamCycler::WatchDevicesCallback));

  return fit::ok(std::move(cycler));
}

void StreamCycler::SetHandlers(StreamCycler::AddCollectionHandler on_add_collection,
                               StreamCycler::RemoveCollectionHandler on_remove_collection,
                               StreamCycler::ShowBufferHandler on_show_buffer,
                               StreamCycler::MuteStateHandler on_mute_changed) {
  add_collection_handler_ = std::move(on_add_collection);
  remove_collection_handler_ = std::move(on_remove_collection);
  show_buffer_handler_ = std::move(on_show_buffer);
  mute_state_handler_ = std::move(on_mute_changed);
}

void StreamCycler::WatchDevicesCallback(std::vector<fuchsia::camera3::WatchDevicesEvent> events) {
  for (auto& event : events) {
    if (event.is_added()) {
      // Connect to device.
      // TODO(fxbug.dev/48506) Properly detect expected device id.
      watcher_->ConnectToDevice(event.added(), device_.NewRequest(dispatcher_));

      // Watch for mute changes.
      device_->WatchMuteState(fit::bind_member(this, &StreamCycler::WatchMuteStateHandler));

      // Fetch camera configurations
      device_->GetConfigurations(
          [this](std::vector<fuchsia::camera3::Configuration> configurations) {
            configurations_ = std::move(configurations);
            // Once we have the known camera configurations, default to the first configuration
            // index. This is automatically chosen in the driver, so we do not need to ask for it.
            // The callback for WatchCurrentConfiguration() will connect to all streams.
            device_->WatchCurrentConfiguration(
                fit::bind_member(this, &StreamCycler::WatchCurrentConfigurationCallback));
          });
    }
  }

  // Hanging get.
  watcher_->WatchDevices(fit::bind_member(this, &StreamCycler::WatchDevicesCallback));
}

void StreamCycler::WatchMuteStateHandler(bool software_muted, bool hardware_muted) {
  mute_state_handler_(software_muted | hardware_muted);
  device_->WatchMuteState(fit::bind_member(this, &StreamCycler::WatchMuteStateHandler));
}

void StreamCycler::ForceNextStreamConfiguration() {
  uint32_t config_index = NextConfigIndex();
  ZX_ASSERT(configurations_.size() > config_index);
  ZX_ASSERT(!configurations_[config_index].streams.empty());
  device_->SetCurrentConfiguration(config_index);
}

void StreamCycler::WatchCurrentConfigurationCallback(uint32_t config_index) {
  // Remember the current device config_index.
  current_config_index_ = config_index;

  // Start connecting to all streams.
  ConnectToAllStreams();

  // After a specified demo period, set the next stream configuration, which will end up cutting off
  // all existing streams.
  async::PostDelayedTask(
      dispatcher_, [this]() { ForceNextStreamConfiguration(); }, kDemoTime);

  // Be ready for configuration changes.
  device_->WatchCurrentConfiguration(
      fit::bind_member(this, &StreamCycler::WatchCurrentConfigurationCallback));
}

void StreamCycler::ConnectToAllStreams() {
  // Connect all streams in descending order to put more stress on the controller.
  ConnectToStream(current_config_index_, configurations_[current_config_index_].streams.size() - 1);
}

void StreamCycler::ConnectToStream(uint32_t config_index, uint32_t stream_index) {
  ZX_ASSERT(configurations_.size() > config_index);
  ZX_ASSERT(configurations_[config_index].streams.size() > stream_index);
  auto image_format = configurations_[config_index].streams[stream_index].image_format;

  // Connect to specific stream
  StreamInfo new_stream_info;
  stream_infos_.emplace(stream_index, std::move(new_stream_info));
  auto& stream = stream_infos_[stream_index].stream;
  auto stream_request = stream.NewRequest(dispatcher_);
  if (config_index == 1 || config_index == 2) {
    stream_infos_[stream_index].source_highlight = 0;
  }

  // Allocate buffer collection
  fuchsia::sysmem::BufferCollectionTokenPtr token_orig;
  allocator_->AllocateSharedCollection(token_orig.NewRequest());
  token_orig->Sync([this, image_format, config_index, stream_index, &stream,
                    token_orig = std::move(token_orig)]() mutable {
    stream->SetBufferCollection(std::move(token_orig));
    stream->WatchBufferCollection([this, image_format, config_index, stream_index, &stream](
                                      fuchsia::sysmem::BufferCollectionTokenHandle token_back) {
      ZX_ASSERT(image_format.coded_width > 0);  // image_format must be reasonable.
      ZX_ASSERT(image_format.coded_height > 0);

      if (add_collection_handler_) {
        auto& stream_info = stream_infos_[stream_index];
        std::ostringstream oss;
        oss << "c" << config_index << "s" << stream_index << ".data";
        stream_info.add_collection_handler_returned_value =
            add_collection_handler_(std::move(token_back), image_format, oss.str());
      } else {
        token_back.BindSync()->Close();
      }

      if (stream_index > 0) {
        ConnectToStream(config_index, stream_index - 1);
      }

      // Kick start the stream
      stream->GetNextFrame([this, stream_index](fuchsia::camera3::FrameInfo frame_info) {
        OnNextFrame(stream_index, std::move(frame_info));
      });
    });
  });

  device_->ConnectToStream(stream_index, std::move(stream_request));

  stream.set_error_handler(
      [this, stream_index](zx_status_t status) { DisconnectStream(stream_index); });
}

void StreamCycler::OnNextFrame(uint32_t stream_index, fuchsia::camera3::FrameInfo frame_info) {
  TRACE_DURATION("camera", "StreamCycler::OnNextFrame");
  TRACE_FLOW_END("camera", "camera3::Stream::GetNextFrame",
                 fsl::GetKoid(frame_info.release_fence.get()));
  auto& stream_info = stream_infos_[stream_index];
  if (show_buffer_handler_ && stream_info.add_collection_handler_returned_value) {
    show_buffer_handler_(stream_info.add_collection_handler_returned_value.value(),
                         frame_info.buffer_index, std::move(frame_info.release_fence),
                         stream_info.highlight);
  } else {
    frame_info.release_fence.reset();
  }
  auto& stream = stream_infos_[stream_index].stream;

  // Set the region of interest if appropriate.
  ZX_ASSERT(configurations_.size() > current_config_index_);
  auto& current_configuration = configurations_[current_config_index_];
  ZX_ASSERT(current_configuration.streams.size() > stream_index);
  auto& current_stream = current_configuration.streams[stream_index];
  if (current_stream.supports_crop_region) {
    const uint32_t limit = kRegionOfInterestFramesPerMoveRatio;
    static uint32_t count = 0;
    ++count;
    if (count >= limit) {
      count = 0;
      auto region = moving_window_.NextWindow();
      stream->SetCropRegion(std::make_unique<fuchsia::math::RectF>(region));
      if (stream_infos_[stream_index].source_highlight) {
        stream_infos_[stream_infos_[stream_index].source_highlight.value()].highlight = region;
      }
    }
  }

  stream->GetNextFrame([this, stream_index](fuchsia::camera3::FrameInfo frame_info) {
    OnNextFrame(stream_index, std::move(frame_info));
  });
}

void StreamCycler::DisconnectStream(uint32_t stream_index) {
  if (remove_collection_handler_) {
    auto& stream_info = stream_infos_[stream_index];
    if (stream_info.add_collection_handler_returned_value) {
      remove_collection_handler_(stream_info.add_collection_handler_returned_value.value());
    }
  }

  stream_infos_.erase(stream_index);
}

uint32_t StreamCycler::NextConfigIndex() {
  ZX_ASSERT(configurations_.size() > 0);
  ZX_ASSERT(current_config_index_ < configurations_.size());
  return (current_config_index_ + 1) % configurations_.size();
}

}  // namespace camera
