/*
 * 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.
 */

#include "VirtualCameraSessionContext.h"

#include <memory>
#include <mutex>
#include <unordered_set>

#include "VirtualCameraStream.h"
#include "aidl/android/hardware/camera/device/StreamConfiguration.h"

namespace android {
namespace companion {
namespace virtualcamera {

using ::aidl::android::hardware::camera::device::BufferCache;
using ::aidl::android::hardware::camera::device::Stream;
using ::aidl::android::hardware::camera::device::StreamBuffer;
using ::aidl::android::hardware::camera::device::StreamConfiguration;

bool VirtualCameraSessionContext::initializeStream(
    const ::aidl::android::hardware::camera::device::Stream& stream) {
  std::lock_guard<std::mutex> lock(mLock);

  auto s = std::make_unique<VirtualCameraStream>(stream);

  const auto& [_, newlyInserted] = mStreams.emplace(
      std::piecewise_construct, std::forward_as_tuple(stream.id),
      std::forward_as_tuple(std::move(s)));
  return newlyInserted;
}

void VirtualCameraSessionContext::closeAllStreams() {
  std::lock_guard<std::mutex> lock(mLock);
  mStreams.clear();
}

bool VirtualCameraSessionContext::importBuffersFromCaptureRequest(
    const ::aidl::android::hardware::camera::device::CaptureRequest&
        captureRequest) {
  std::lock_guard<std::mutex> lock(mLock);

  for (const StreamBuffer& buffer : captureRequest.outputBuffers) {
    auto it = mStreams.find(buffer.streamId);
    if (it == mStreams.end()) {
      ALOGE("%s: Cannot import buffer for unknown stream with id %d", __func__,
            buffer.streamId);
      return false;
    }
    VirtualCameraStream& stream = *it->second;
    if (stream.getHardwareBuffer(buffer.bufferId) != nullptr) {
      // This buffer is already imported.
      continue;
    }

    if (stream.importBuffer(buffer) == nullptr) {
      ALOGE("%s: Failed to import buffer %" PRId64 " for streamId %d", __func__,
            buffer.bufferId, buffer.streamId);
      return false;
    }
  }

  return true;
}

void VirtualCameraSessionContext::removeBufferCaches(
    const std::vector<BufferCache>& cachesToRemove) {
  std::lock_guard<std::mutex> lock(mLock);
  for (const auto& bufferCache : cachesToRemove) {
    auto it = mStreams.find(bufferCache.streamId);
    if (it == mStreams.end()) {
      ALOGE("%s: Ask to remove buffer %" PRId64 " from unknown stream %d",
            __func__, bufferCache.bufferId, bufferCache.streamId);
      continue;
    }
    if (it->second->removeBuffer(bufferCache.bufferId)) {
      ALOGD("%s: Successfully removed buffer %" PRId64
            " from cache of stream %d",
            __func__, bufferCache.bufferId, bufferCache.streamId);
    } else {
      ALOGE("%s: Failed to remove buffer %" PRId64 " from cache of stream %d",
            __func__, bufferCache.bufferId, bufferCache.streamId);
    }
  }
}

void VirtualCameraSessionContext::removeStreamsNotInStreamConfiguration(
    const StreamConfiguration& streamConfiguration) {
  std::unordered_set<int> newConfigurationStreamIds;
  for (const Stream& stream : streamConfiguration.streams) {
    newConfigurationStreamIds.insert(stream.id);
  }

  std::lock_guard<std::mutex> lock(mLock);
  for (auto it = mStreams.begin(); it != mStreams.end();) {
    if (newConfigurationStreamIds.find(it->first) ==
        newConfigurationStreamIds.end()) {
      ALOGV(
          "Disposing of stream %d, since it is not referenced by new "
          "configuration.",
          it->first);
      it = mStreams.erase(it);
    } else {
      ++it;
    }
  }
}

std::optional<Stream> VirtualCameraSessionContext::getStreamConfig(
    int streamId) const {
  std::lock_guard<std::mutex> lock(mLock);
  auto it = mStreams.find(streamId);
  if (it == mStreams.end()) {
    ALOGE("%s: StreamBuffer references buffer of unknown streamId %d", __func__,
          streamId);
    return std::optional<Stream>();
  }
  return {it->second->getStreamConfig()};
}

std::shared_ptr<AHardwareBuffer> VirtualCameraSessionContext::fetchHardwareBuffer(
    const int streamId, const int bufferId) const {
  std::lock_guard<std::mutex> lock(mLock);
  auto it = mStreams.find(streamId);
  if (it == mStreams.end()) {
    ALOGE("%s: StreamBuffer references buffer of unknown streamId %d", __func__,
          streamId);
    return nullptr;
  }
  return it->second->getHardwareBuffer(bufferId);
}

std::shared_ptr<EglFrameBuffer>
VirtualCameraSessionContext::fetchOrCreateEglFramebuffer(
    const EGLDisplay eglDisplay, const int streamId, const int bufferId) {
  std::lock_guard<std::mutex> lock(mLock);
  auto it = mStreams.find(streamId);
  if (it == mStreams.end()) {
    ALOGE("%s: StreamBuffer references buffer of unknown streamId %d", __func__,
          streamId);
    return nullptr;
  }
  return it->second->getEglFrameBuffer(eglDisplay, bufferId);
}

std::set<int> VirtualCameraSessionContext::getStreamIds() const {
  std::set<int> result;
  std::lock_guard<std::mutex> lock(mLock);
  for (const auto& [streamId, _] : mStreams) {
    result.insert(streamId);
  }
  return result;
}

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