/* Copyright 2022 The ChromiumOS Authors
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "hal/fake/camera_hal.h"

#include <algorithm>
#include <memory>
#include <utility>

#include <base/containers/contains.h>
#include <base/no_destructor.h>
#include <base/strings/string_number_conversions.h>
#include <base/task/sequenced_task_runner.h>

#include "cros-camera/common.h"
#include "cros-camera/cros_camera_hal.h"

#include "hal/fake/metadata_handler.h"

namespace cros {

namespace {
// The default fake hal spec file. The file should contain a JSON that is
// parsed to HalSpec struct.
constexpr const char kDefaultFakeHalSpecFile[] = "/etc/camera/fake_hal.json";
constexpr const char kOverrideFakeHalSpecFile[] = "/run/camera/fake_hal.json";

// This is the sleep time (0.3s) between reporting disconnect and connect event
// to upper layer, to avoid race condition in Chrome.
// TODO(b:261682032): Check if the time can be lower, and/or fix the issue in
// Chrome so this is not needed.
constexpr const base::TimeDelta kReconnectDelay = base::Milliseconds(300);

int camera_device_open_ext(const hw_module_t* module,
                           const char* name,
                           hw_device_t** device,
                           ClientType client_type) {
  // Make sure hal adapter loads the correct symbol.
  if (module != &HAL_MODULE_INFO_SYM.common) {
    LOGF(ERROR) << "Invalid module " << module << " expected "
                << &HAL_MODULE_INFO_SYM.common;
    return -EINVAL;
  }

  int id;
  if (!base::StringToInt(name, &id)) {
    LOGF(ERROR) << "Invalid camera name " << name;
    return -EINVAL;
  }
  return CameraHal::GetInstance().OpenDevice(id, module, device, client_type);
}

int get_camera_info_ext(int id,
                        struct camera_info* info,
                        ClientType client_type) {
  return CameraHal::GetInstance().GetCameraInfo(id, info, client_type);
}

int camera_device_open(const hw_module_t* module,
                       const char* name,
                       hw_device_t** device) {
  return camera_device_open_ext(module, name, device, ClientType::kChrome);
}

int get_number_of_cameras() {
  return CameraHal::GetInstance().GetNumberOfCameras();
}

int get_camera_info(int id, struct camera_info* info) {
  return get_camera_info_ext(id, info, ClientType::kChrome);
}

int set_callbacks(const camera_module_callbacks_t* callbacks) {
  return CameraHal::GetInstance().SetCallbacks(callbacks);
}

int init() {
  return CameraHal::GetInstance().Init();
}

void set_up(CameraMojoChannelManagerToken* token) {
  CameraHal::GetInstance().SetUp(token);
}

void tear_down() {
  CameraHal::GetInstance().TearDown();
}

void set_privacy_switch_callback(PrivacySwitchStateChangeCallback callback) {
  CameraHal::GetInstance().SetPrivacySwitchCallback(callback);
}

int open_legacy(const struct hw_module_t* module,
                const char* id,
                uint32_t halVersion,
                struct hw_device_t** device) {
  return -ENOSYS;
}

int set_torch_mode(const char* camera_id, bool enabled) {
  return -ENOSYS;
}

}  // namespace

CameraHal::CameraHal() {
  // The constructor is first called by set_up which is not on the same
  // sequence as the other methods this class is run on.
  DETACH_FROM_SEQUENCE(sequence_checker_);
}

CameraHal::~CameraHal() = default;

CameraHal& CameraHal::GetInstance() {
  // Leak the static camera HAL here, since it has a non-trivial destructor
  // (from ReloadableConfigFile -> base::FilePathWatcher).
  static base::NoDestructor<CameraHal> camera_hal;
  return *camera_hal;
}

int CameraHal::GetNumberOfCameras() const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  return 0;
}

int CameraHal::SetCallbacks(const camera_module_callbacks_t* callbacks) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  callbacks_ = callbacks;
  ApplySpec();

  return 0;
}

int CameraHal::Init() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  task_runner_ = base::SequencedTaskRunner::GetCurrentDefault();
  config_file_ = std::make_unique<ReloadableConfigFile>(
      ReloadableConfigFile::Options{base::FilePath(kDefaultFakeHalSpecFile),
                                    base::FilePath(kOverrideFakeHalSpecFile)});
  config_file_->SetCallback(
      base::BindRepeating(&CameraHal::OnSpecUpdated, base::Unretained(this)));

  return 0;
}

void CameraHal::SetUp(CameraMojoChannelManagerToken* token) {
  mojo_manager_token_ = token;
}

void CameraHal::TearDown() {}

void CameraHal::SetPrivacySwitchCallback(
    PrivacySwitchStateChangeCallback callback) {}

int CameraHal::OpenDevice(int id,
                          const hw_module_t* module,
                          hw_device_t** hw_device,
                          ClientType client_type) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  VLOGFID(1, id);

  if (!IsCameraIdValid(id)) {
    LOGF(ERROR) << "Camera ID " << id << " is invalid";
    return -ENODEV;
  }

  auto it = std::find_if(hal_spec_.cameras.begin(), hal_spec_.cameras.end(),
                         [id](const auto& spec) { return spec.id == id; });
  CHECK(it != hal_spec_.cameras.end());

  cameras_[id] = std::make_unique<CameraClient>(
      id, static_metadata_[id], request_template_[id], module, hw_device, *it);

  int ret = cameras_[id]->OpenDevice();
  if (ret != 0) {
    cameras_.erase(id);
    return -ENODEV;
  }

  return 0;
}

bool CameraHal::IsCameraIdValid(int id) {
  return base::Contains(hal_spec_.cameras, id,
                        [](const auto& spec) { return spec.id; });
}

int CameraHal::GetCameraInfo(int id,
                             struct camera_info* info,
                             ClientType client_type) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  VLOGFID(1, id);

  if (!IsCameraIdValid(id)) {
    LOGF(ERROR) << "Camera ID " << id << " is invalid";
    return -EINVAL;
  }

  info->facing = CAMERA_FACING_EXTERNAL;
  info->orientation = 0;
  info->device_version = CAMERA_DEVICE_API_VERSION_3_5;
  info->static_camera_characteristics = static_metadata_[id].getAndLock();
  info->resource_cost = 0;
  info->conflicting_devices = nullptr;
  info->conflicting_devices_length = 0;
  return 0;
}

void CameraHal::OnSpecUpdated(const base::Value::Dict& json_values) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  auto hal_spec = ParseHalSpecFromJsonValue(json_values);
  if (!hal_spec.has_value()) {
    LOGF(WARNING) << "config file is not formatted correctly, ignored.";
    return;
  }

  hal_spec_ = hal_spec.value();
  ApplySpec();
}

bool CameraHal::SetUpCamera(int id, const CameraSpec& spec) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  android::CameraMetadata static_metadata, request_template;

  if (!FillDefaultMetadata(&static_metadata, &request_template, spec)) {
    return false;
  }

  static_metadata_[id] = std::move(static_metadata);
  request_template_[id] = std::move(request_template);

  return true;
}

void CameraHal::TearDownCamera(int id) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  static_metadata_.erase(id);
  request_template_.erase(id);
}

void CameraHal::NotifyCameraConnected(int id, bool connected) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(callbacks_ != nullptr);

  callbacks_->camera_device_status_change(
      callbacks_, id,
      connected ? CAMERA_DEVICE_STATUS_PRESENT
                : CAMERA_DEVICE_STATUS_NOT_PRESENT);
}

void CameraHal::ApplySpec() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  if (callbacks_ == nullptr) {
    // Spec will be applied when callback is set.
    return;
  }

  bool should_apply_delayed_spec = false;
  auto new_applied_spec = hal_spec_;

  for (const auto& old_camera_spec : applied_hal_spec_.cameras) {
    int id = old_camera_spec.id;
    auto it = std::find_if(new_applied_spec.cameras.begin(),
                           new_applied_spec.cameras.end(),
                           [&](const auto& spec) { return spec.id == id; });
    // TODO(pihsun): Might need to close the camera if some currently opened
    // camera is removed in spec.
    if (it == new_applied_spec.cameras.end()) {
      // Camera entry removed.
      if (old_camera_spec.connected) {
        VLOGF(1) << "Removing camera " << id;
        NotifyCameraConnected(id, false);
        TearDownCamera(id);
      }
    } else {
      if (it->connected != old_camera_spec.connected) {
        // Device connected state changed.
        VLOGF(1) << "Camera " << id << " connected state changed "
                 << old_camera_spec.connected << "->" << it->connected;
        NotifyCameraConnected(id, it->connected);
      } else if (it->connected) {
        bool should_reconnect = false;
        if (it->supported_formats != old_camera_spec.supported_formats) {
          VLOGF(1) << "Camera " << id << " supported formats changed";
          NotifyCameraConnected(id, false);
          TearDownCamera(id);

          // Supported format changes change static metadata, so we need to
          // regenerate static metadata here.
          if (!SetUpCamera(id, *it)) {
            // TODO(pihsun): Better handle error? We should at least remove the
            // entry from the new spec.
            LOGF(WARNING) << "Error when setting up camera id " << id;
            continue;
          }
          should_reconnect = true;
        } else if (it->frames != old_camera_spec.frames) {
          // TODO(pihsun): For frames spec change it's possible to just start
          // returning new frames in the CameraClient instead of simulating
          // unplug / plug the camera.
          VLOGF(1) << "Camera " << id << " frames spec changed";
          NotifyCameraConnected(id, false);
          should_reconnect = true;
        }
        if (should_reconnect) {
          should_apply_delayed_spec = true;
          it->connected = false;
        }
      }
    }
  }
  for (const auto& camera_spec : new_applied_spec.cameras) {
    int id = camera_spec.id;
    if (std::none_of(applied_hal_spec_.cameras.begin(),
                     applied_hal_spec_.cameras.end(),
                     [&](const auto& spec) { return spec.id == id; })) {
      // New device.
      VLOGF(1) << "Adding camera " << id;
      if (!SetUpCamera(id, camera_spec)) {
        // TODO(pihsun): Better handle error? We should at least remove the
        // entry from the new spec.
        LOGF(WARNING) << "Error when setting up camera id " << id;
        continue;
      }
      NotifyCameraConnected(id, camera_spec.connected);
    }
  }

  applied_hal_spec_ = new_applied_spec;

  // TODO(b:261682032): This is for workaround that fake HAL plugging /
  // unplugging camera too quickly will cause issue in Chrome.
  if (should_apply_delayed_spec) {
    apply_spec_timer_.Start(FROM_HERE, kReconnectDelay, this,
                            &CameraHal::ApplySpec);
  }
}

void CameraHal::CloseDevice(int id) {
  VLOGFID(1, id);
  DCHECK(task_runner_);
  // The CameraHal is Singleton with NoDestructor so base::Unretained(this)
  // will always be valid.
  // Most of the work, like stopping the request handler thread, is done in
  // CameraClient::CloseDevice, and this only removes the CameraClient from the
  // CameraHal.
  task_runner_->PostTask(FROM_HERE,
                         base::BindOnce(&CameraHal::CloseDeviceOnHalThread,
                                        base::Unretained(this), id));
}

void CameraHal::CloseDeviceOnHalThread(int id) {
  VLOGFID(1, id);
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  cameras_.erase(id);
}

int camera_device_close(struct hw_device_t* hw_device) {
  camera3_device_t* cam_dev = reinterpret_cast<camera3_device_t*>(hw_device);
  CameraClient* cam = static_cast<CameraClient*>(cam_dev->priv);
  if (!cam) {
    LOGF(ERROR) << "Camera device is NULL";
    return -EIO;
  }
  cam_dev->priv = nullptr;
  int ret = cam->CloseDevice();
  CameraHal::GetInstance().CloseDevice(cam->GetId());
  return ret;
}

}  // namespace cros

static hw_module_methods_t gCameraModuleMethods = {
    .open = cros::camera_device_open};

camera_module_t HAL_MODULE_INFO_SYM CROS_CAMERA_EXPORT = {
    .common = {.tag = HARDWARE_MODULE_TAG,
               .module_api_version = CAMERA_MODULE_API_VERSION_2_4,
               .hal_api_version = HARDWARE_HAL_API_VERSION,
               .id = CAMERA_HARDWARE_MODULE_ID,
               // TODO(pihsun): Extract the module name to a constant if more
               // tests needs to have special case for fake HAL.
               .name = "Fake Camera HAL",
               .author = "The ChromiumOS Authors",
               .methods = &gCameraModuleMethods,
               .dso = nullptr,
               .reserved = {}},
    .get_number_of_cameras = cros::get_number_of_cameras,
    .get_camera_info = cros::get_camera_info,
    .set_callbacks = cros::set_callbacks,
    // TODO(pihsun): Implement faking vendor tags.
    .get_vendor_tag_ops = nullptr,
    .open_legacy = cros::open_legacy,
    .set_torch_mode = cros::set_torch_mode,
    .init = cros::init,
    .reserved = {}};

cros::cros_camera_hal_t CROS_CAMERA_HAL_INFO_SYM CROS_CAMERA_EXPORT = {
    .set_up = cros::set_up,
    .tear_down = cros::tear_down,
    .set_privacy_switch_callback = cros::set_privacy_switch_callback,
    .camera_device_open_ext = cros::camera_device_open_ext,
    .get_camera_info_ext = cros::get_camera_info_ext};
