/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// #define LOG_NDEBUG 0
#define LOG_TAG "VirtualCameraProvider"
#include "VirtualCameraProvider.h"

#include <atomic>
#include <memory>
#include <mutex>
#include <tuple>
#include <utility>

#include "VirtualCameraDevice.h"
#include "aidl/android/hardware/camera/common/Status.h"
#include "log/log.h"
#include "util/Util.h"

namespace android {
namespace companion {
namespace virtualcamera {

using ::aidl::android::companion::virtualcamera::IVirtualCameraCallback;
using ::aidl::android::companion::virtualcamera::SupportedStreamConfiguration;
using ::aidl::android::hardware::camera::common::CameraDeviceStatus;
using ::aidl::android::hardware::camera::common::Status;
using ::aidl::android::hardware::camera::common::VendorTagSection;
using ::aidl::android::hardware::camera::device::ICameraDevice;
using ::aidl::android::hardware::camera::provider::CameraIdAndStreamCombination;
using ::aidl::android::hardware::camera::provider::ConcurrentCameraIdCombination;
using ::aidl::android::hardware::camera::provider::ICameraProviderCallback;

// TODO(b/301023410) Make camera id range configurable / dynamic
// based on already registered devices.
std::atomic_int VirtualCameraProvider::sNextId{42};

ndk::ScopedAStatus VirtualCameraProvider::setCallback(
    const std::shared_ptr<ICameraProviderCallback>& in_callback) {
  ALOGV("%s", __func__);

  if (in_callback == nullptr) {
    return cameraStatus(Status::ILLEGAL_ARGUMENT);
  }

  {
    const std::lock_guard<std::mutex> lock(mLock);
    mCameraProviderCallback = in_callback;

    for (const auto& [cameraName, _] : mCameras) {
      auto ret = mCameraProviderCallback->cameraDeviceStatusChange(
          cameraName, CameraDeviceStatus::PRESENT);
      if (!ret.isOk()) {
        ALOGE("Failed to announce camera status change: %s",
              ret.getDescription().c_str());
      }
    }
  }
  return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus VirtualCameraProvider::getVendorTags(
    std::vector<VendorTagSection>* _aidl_return) {
  ALOGV("%s", __func__);

  if (_aidl_return == nullptr) {
    return cameraStatus(Status::ILLEGAL_ARGUMENT);
  }

  // No vendor tags supported.
  _aidl_return->clear();
  return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus VirtualCameraProvider::getCameraIdList(
    std::vector<std::string>* _aidl_return) {
  ALOGV("%s", __func__);

  if (_aidl_return == nullptr) {
    return cameraStatus(Status::ILLEGAL_ARGUMENT);
  }

  {
    const std::lock_guard<std::mutex> lock(mLock);
    _aidl_return->clear();
    _aidl_return->reserve(mCameras.size());
    for (const auto& [cameraName, _] : mCameras) {
      _aidl_return->emplace_back(cameraName);
    }
  }
  return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus VirtualCameraProvider::getCameraDeviceInterface(
    const std::string& in_cameraDeviceName,
    std::shared_ptr<ICameraDevice>* _aidl_return) {
  ALOGV("%s cameraDeviceName %s", __func__, in_cameraDeviceName.c_str());

  if (_aidl_return == nullptr) {
    return cameraStatus(Status::ILLEGAL_ARGUMENT);
  }

  {
    const std::lock_guard<std::mutex> lock(mLock);
    const auto it = mCameras.find(in_cameraDeviceName);
    *_aidl_return = (it == mCameras.end()) ? nullptr : it->second;
  }

  return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus VirtualCameraProvider::notifyDeviceStateChange(
    int64_t in_deviceState) {
  ALOGV("%s", __func__);
  (void)in_deviceState;
  return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus VirtualCameraProvider::getConcurrentCameraIds(
    std::vector<ConcurrentCameraIdCombination>* _aidl_return) {
  ALOGV("%s", __func__);
  if (_aidl_return == nullptr) {
    return cameraStatus(Status::ILLEGAL_ARGUMENT);
  }

  // No support for any concurrent combination.
  _aidl_return->clear();
  return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus VirtualCameraProvider::isConcurrentStreamCombinationSupported(
    const std::vector<CameraIdAndStreamCombination>& in_configs,
    bool* _aidl_return) {
  ALOGV("%s", __func__);
  (void)in_configs;
  if (_aidl_return == nullptr) {
    return cameraStatus(Status::ILLEGAL_ARGUMENT);
  }

  // No support for any stream combination at the moment.
  *_aidl_return = false;
  return ndk::ScopedAStatus::ok();
}

std::shared_ptr<VirtualCameraDevice> VirtualCameraProvider::createCamera(
    const std::vector<SupportedStreamConfiguration>& supportedInputConfig,
    std::shared_ptr<IVirtualCameraCallback> virtualCameraClientCallback) {
  auto camera = ndk::SharedRefBase::make<VirtualCameraDevice>(
      sNextId++, supportedInputConfig, virtualCameraClientCallback);
  std::shared_ptr<ICameraProviderCallback> callback;
  {
    const std::lock_guard<std::mutex> lock(mLock);
    if (mCameras.find(camera->getCameraName()) != mCameras.end()) {
      ALOGE("Camera with identical name already exists.");
      return nullptr;
    }
    mCameras.emplace(std::piecewise_construct,
                     std::forward_as_tuple(camera->getCameraName()),
                     std::forward_as_tuple(camera));
    callback = mCameraProviderCallback;
  }

  if (callback != nullptr) {
    auto ret = callback->cameraDeviceStatusChange(camera->getCameraName(),
                                                  CameraDeviceStatus::PRESENT);
    if (!ret.isOk()) {
      ALOGE("Failed to announce camera %s status change (PRESENT): %s",
            camera->getCameraName().c_str(), ret.getDescription().c_str());
    }
  }
  return camera;
}

std::shared_ptr<VirtualCameraDevice> VirtualCameraProvider::getCamera(
    const std::string& cameraName) {
  const std::lock_guard<std::mutex> lock(mLock);
  auto it = mCameras.find(cameraName);
  return it == mCameras.end() ? nullptr : it->second;
}

bool VirtualCameraProvider::removeCamera(const std::string& name) {
  std::shared_ptr<ICameraProviderCallback> callback;
  {
    const std::lock_guard<std::mutex> lock(mLock);
    auto it = mCameras.find(name);
    if (it == mCameras.end()) {
      ALOGE("Cannot remove camera %s: no such camera", name.c_str());
      return false;
    }
    // TODO(b/301023410) Gracefully shut down camera.
    mCameras.erase(it);
    callback = mCameraProviderCallback;
  }

  if (callback != nullptr) {
    auto ret = callback->cameraDeviceStatusChange(
        name, CameraDeviceStatus::NOT_PRESENT);
    if (!ret.isOk()) {
      ALOGE("Failed to announce camera %s status change (NOT_PRESENT): %s",
            name.c_str(), ret.getDescription().c_str());
    }
  }

  return true;
}

}  // namespace virtualcamera
}  // namespace companion
}  // namespace android
