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

#include <fuchsia/camera2/cpp/fidl.h>
#include <fuchsia/sysmem/cpp/fidl.h>
#include <lib/async/default.h>
#include <lib/async/dispatcher.h>
#include <lib/fidl/cpp/binding.h>
#include <lib/fit/result.h>
#include <lib/syslog/cpp/macros.h>
#include <zircon/errors.h>
#include <zircon/types.h>

#include <array>
#include <memory>
#include <sstream>
#include <unordered_set>

namespace camera {

// NOTE: these must be a superset of the formats defined in
// //src/camera/bin/device/test/take_controller.cc
// TODO(fxbug.dev/49137): improve legacy test fakes
static constexpr std::array<fuchsia::sysmem::ImageFormat_2, 3> kFakeImageFormats{{
    {
        .pixel_format =
            {
                .type = fuchsia::sysmem::PixelFormatType::NV12,
            },
        .coded_width = 1920,
        .coded_height = 1080,
        .bytes_per_row = 1920,
        .color_space =
            {
                .type = fuchsia::sysmem::ColorSpaceType::REC601_NTSC,
            },
    },
    {
        .pixel_format =
            {
                .type = fuchsia::sysmem::PixelFormatType::NV12,
            },
        .coded_width = 1280,
        .coded_height = 720,
        .bytes_per_row = 1920,
        .color_space =
            {
                .type = fuchsia::sysmem::ColorSpaceType::REC601_NTSC,
            },
    },
    {
        .pixel_format =
            {
                .type = fuchsia::sysmem::PixelFormatType::NV12,
            },
        .coded_width = 1024,
        .coded_height = 576,
        .bytes_per_row = 1920,
        .color_space =
            {
                .type = fuchsia::sysmem::ColorSpaceType::REC601_NTSC,
            },
    },
}};

class FakeLegacyStreamImpl : public FakeLegacyStream, public fuchsia::camera2::Stream {
 public:
  FakeLegacyStreamImpl(fuchsia::sysmem::AllocatorPtr& allocator)
      : binding_(this), allocator_(allocator) {}

  void CheckSameThread() {
    auto dispatcher = async_get_default_dispatcher();
    if (dispatcher) {
      ZX_ASSERT_MSG(dispatcher == binding_.dispatcher(), "FakeLegacyStream is not thread-safe!");
    }
  }

  // |camera::FakeLegacyStream|
  fit::result<void, std::string> StreamClientStatus() override {
    if (client_error_count_ == 0) {
      return fit::ok();
    }
    auto error_string = client_error_explanation_.str();
    return fit::error(std::move(error_string));
  }

  zx_status_t SendFrameAvailable(fuchsia::camera2::FrameAvailableInfo info) override {
    CheckSameThread();
    if (stopped_) {
      FX_LOGS(INFO) << "Client has not started the stream";
      return ZX_ERR_BAD_STATE;
    }
    if (outstanding_error_frame_) {
      FX_LOGS(INFO) << "Client has not yet acknowledged a previous error frame";
      return ZX_ERR_BAD_STATE;
    }
    if (info.frame_status == fuchsia::camera2::FrameStatus::OK) {
      auto it = outstanding_buffer_ids_.find(info.buffer_id);
      if (it != outstanding_buffer_ids_.end()) {
        FX_LOGS(INFO) << "Client has not yet returned buffer_id " << info.buffer_id;
        return ZX_ERR_BAD_STATE;
      }
      outstanding_buffer_ids_.insert(info.buffer_id);
    } else {
      outstanding_error_frame_ = true;
    }
    binding_.events().OnFrameAvailable(std::move(info));
    return ZX_OK;
  }

  bool IsStreaming() override {
    CheckSameThread();
    return !stopped_;
  }

  bool IsOutstanding(uint32_t buffer_id) override {
    CheckSameThread();
    return outstanding_buffer_ids_.find(buffer_id) != outstanding_buffer_ids_.end();
  };

  std::tuple<float, float, float, float> GetRegionOfInterest() override {
    return region_of_interest_;
  }

  uint32_t GetImageFormat() override { return image_format_; }

 private:
  std::stringstream& ClientErrors() {
    if (client_error_count_ > 0) {
      client_error_explanation_ << std::endl;
    }
    client_error_explanation_ << client_error_count_++ << ": ";
    return client_error_explanation_;
  }

  // |fuchsia::camera2::Stream|
  void Start() override {
    if (!stopped_) {
      ClientErrors() << "Client called Start while stream is already started";
    }
    stopped_ = false;
  }

  void Stop() override {
    if (stopped_) {
      ClientErrors() << "Client called Stop while stream is already stopped";
    }
    stopped_ = true;
  }

  void ReleaseFrame(uint32_t buffer_id) override {
    auto it = outstanding_buffer_ids_.find(buffer_id);
    if (it == outstanding_buffer_ids_.end()) {
      ClientErrors() << "Client called Release with unowned buffer_id " << buffer_id;
    } else {
      outstanding_buffer_ids_.erase(it);
    }
  }

  void AcknowledgeFrameError() override {
    if (!outstanding_error_frame_) {
      ClientErrors()
          << "Client called AcknowledgeFrameError without having received any new error frames";
    }
    outstanding_error_frame_ = false;
  }

  void SetRegionOfInterest(float x_min, float y_min, float x_max, float y_max,
                           SetRegionOfInterestCallback callback) override {
    if (x_min < 0 || y_min < 0 || x_min >= x_max || y_min >= y_max) {
      ClientErrors() << "Client called SetRegionOfInterest with invalid args: " << x_min << ", "
                     << y_min << ", " << x_max << ", " << y_max;
      callback(ZX_ERR_INVALID_ARGS);
    } else {
      region_of_interest_ = {x_min, y_min, x_max, y_max};
      callback(ZX_OK);
    }
  }

  void SetImageFormat(uint32_t image_format_index, SetImageFormatCallback callback) override {
    if (image_format_index >= kFakeImageFormats.size()) {
      ClientErrors() << "Client called SetImageFormat with invalid index: " << image_format_index;
      callback(ZX_ERR_INVALID_ARGS);
    } else {
      image_format_ = image_format_index;
      callback(ZX_OK);
    }
  }

  void GetImageFormats(GetImageFormatsCallback callback) override {
    callback({kFakeImageFormats.begin(), kFakeImageFormats.end()});
  }

  void GetBuffers(GetBuffersCallback callback) override {
    fuchsia::sysmem::BufferCollectionTokenHandle token;
    allocator_->AllocateSharedCollection(token.NewRequest());
    callback(std::move(token));
  }

  fidl::Binding<fuchsia::camera2::Stream> binding_;
  bool stopped_ = true;
  std::unordered_set<uint32_t> outstanding_buffer_ids_;
  bool outstanding_error_frame_ = false;
  uint32_t client_error_count_ = 0;
  std::stringstream client_error_explanation_;
  std::tuple<float, float, float, float> region_of_interest_{0.0f, 0.0f, 1.0f, 1.0f};
  uint32_t image_format_ = 0;
  fuchsia::sysmem::AllocatorPtr& allocator_;

  friend class FakeLegacyStream;
};

fit::result<std::unique_ptr<FakeLegacyStream>, zx_status_t> FakeLegacyStream::Create(
    fidl::InterfaceRequest<fuchsia::camera2::Stream> request,
    fuchsia::sysmem::AllocatorPtr& allocator, uint32_t format_index,

    async_dispatcher_t* dispatcher) {
  auto impl = std::make_unique<FakeLegacyStreamImpl>(allocator);
  zx_status_t status = impl->binding_.Bind(std::move(request), dispatcher);
  impl->image_format_ = format_index;
  if (status) {
    return fit::error(status);
  }
  impl->binding_.set_error_handler(
      [impl = impl.get()](zx_status_t status) { impl->ClientErrors() << "Client disconnected"; });
  return fit::ok(std::move(impl));
}

}  // namespace camera
