/*
 *  Copyright 2018 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "modules/desktop_capture/linux/wayland/base_capturer_pipewire.h"

#include "modules/desktop_capture/desktop_capture_options.h"
#include "modules/desktop_capture/desktop_capturer.h"
#include "modules/desktop_capture/linux/wayland/restore_token_manager.h"
#include "modules/desktop_capture/linux/wayland/xdg_desktop_portal_utils.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "screencast_portal.h"

namespace webrtc {

namespace {

using xdg_portal::RequestResponse;
using xdg_portal::ScreenCapturePortalInterface;
using xdg_portal::SessionDetails;

}  // namespace

BaseCapturerPipeWire::BaseCapturerPipeWire(const DesktopCaptureOptions& options,
                                           CaptureType type)
    : BaseCapturerPipeWire(options,
                           std::make_unique<ScreenCastPortal>(type, this)) {
  is_screencast_portal_ = true;
}

BaseCapturerPipeWire::BaseCapturerPipeWire(
    const DesktopCaptureOptions& options,
    std::unique_ptr<ScreenCapturePortalInterface> portal)
    : options_(options),
      is_screencast_portal_(false),
      portal_(std::move(portal)) {
  source_id_ = RestoreTokenManager::GetInstance().GetUnusedId();
}

BaseCapturerPipeWire::~BaseCapturerPipeWire() {
  options_.screencast_stream()->StopScreenCastStream();
}

void BaseCapturerPipeWire::OnScreenCastRequestResult(RequestResponse result,
                                                     uint32_t stream_node_id,
                                                     int fd) {
  is_portal_open_ = false;

  // Reset the value of capturer_failed_ in case we succeed below. If we fail,
  // then it'll set it to the right value again soon enough.
  capturer_failed_ = false;
  if (result != RequestResponse::kSuccess ||
      !options_.screencast_stream()->StartScreenCastStream(
          stream_node_id, fd, options_.get_width(), options_.get_height())) {
    capturer_failed_ = true;
    RTC_LOG(LS_ERROR) << "ScreenCastPortal failed: "
                      << static_cast<uint>(result);
  } else if (ScreenCastPortal* screencast_portal = GetScreenCastPortal()) {
    if (!screencast_portal->RestoreToken().empty()) {
      RestoreTokenManager::GetInstance().AddToken(
          source_id_, screencast_portal->RestoreToken());
    }
  }

  if (!delegated_source_list_observer_)
    return;

  switch (result) {
    case RequestResponse::kUnknown:
      RTC_DCHECK_NOTREACHED();
      break;
    case RequestResponse::kSuccess:
      delegated_source_list_observer_->OnSelection();
      break;
    case RequestResponse::kUserCancelled:
      delegated_source_list_observer_->OnCancelled();
      break;
    case RequestResponse::kError:
      delegated_source_list_observer_->OnError();
      break;
  }
}

void BaseCapturerPipeWire::OnScreenCastSessionClosed() {
  if (!capturer_failed_) {
    options_.screencast_stream()->StopScreenCastStream();
  }
}

void BaseCapturerPipeWire::UpdateResolution(uint32_t width, uint32_t height) {
  if (!capturer_failed_) {
    options_.screencast_stream()->UpdateScreenCastStreamResolution(width,
                                                                   height);
  }
}

void BaseCapturerPipeWire::Start(Callback* callback) {
  RTC_DCHECK(!callback_);
  RTC_DCHECK(callback);

  callback_ = callback;

  if (ScreenCastPortal* screencast_portal = GetScreenCastPortal()) {
    screencast_portal->SetPersistMode(
        ScreenCastPortal::PersistMode::kTransient);
    if (selected_source_id_) {
      screencast_portal->SetRestoreToken(
          RestoreTokenManager::GetInstance().TakeToken(selected_source_id_));
    }
  }

  is_portal_open_ = true;
  portal_->Start();
}

void BaseCapturerPipeWire::CaptureFrame() {
  if (capturer_failed_) {
    // This could be recoverable if the source list is re-summoned; but for our
    // purposes this is fine, since it requires intervention to resolve and
    // essentially starts a new capture.
    callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr);
    return;
  }

  std::unique_ptr<DesktopFrame> frame =
      options_.screencast_stream()->CaptureFrame();

  if (!frame || !frame->data()) {
    callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
    return;
  }

  // TODO(julien.isorce): http://crbug.com/945468. Set the icc profile on
  // the frame, see ScreenCapturerX11::CaptureFrame.

  frame->set_capturer_id(DesktopCapturerId::kWaylandCapturerLinux);
  callback_->OnCaptureResult(Result::SUCCESS, std::move(frame));
}

bool BaseCapturerPipeWire::GetSourceList(SourceList* sources) {
  RTC_DCHECK(sources->size() == 0);
  // List of available screens is already presented by the xdg-desktop-portal,
  // so we just need a (valid) source id for any callers to pass around, even
  // though it doesn't mean anything to us. Until the user selects a source in
  // xdg-desktop-portal we'll just end up returning empty frames. Note that "0"
  // is often treated as a null/placeholder id, so we shouldn't use that.
  // TODO(https://crbug.com/1297671): Reconsider type of ID when plumbing
  // token that will enable stream re-use.
  sources->push_back({source_id_});
  return true;
}

bool BaseCapturerPipeWire::SelectSource(SourceId id) {
  // Screen selection is handled by the xdg-desktop-portal.
  selected_source_id_ = id;
  return true;
}

DelegatedSourceListController*
BaseCapturerPipeWire::GetDelegatedSourceListController() {
  return this;
}

void BaseCapturerPipeWire::Observe(Observer* observer) {
  RTC_DCHECK(!delegated_source_list_observer_ || !observer);
  delegated_source_list_observer_ = observer;
}

void BaseCapturerPipeWire::EnsureVisible() {
  RTC_DCHECK(callback_);
  if (is_portal_open_)
    return;

  // Clear any previously selected state/capture
  portal_->Stop();
  options_.screencast_stream()->StopScreenCastStream();

  // Get a new source id to reflect that the source has changed.
  source_id_ = RestoreTokenManager::GetInstance().GetUnusedId();

  is_portal_open_ = true;
  portal_->Start();
}

void BaseCapturerPipeWire::EnsureHidden() {
  if (!is_portal_open_)
    return;

  is_portal_open_ = false;
  portal_->Stop();
}

SessionDetails BaseCapturerPipeWire::GetSessionDetails() {
  return portal_->GetSessionDetails();
}

ScreenCastPortal* BaseCapturerPipeWire::GetScreenCastPortal() {
  return is_screencast_portal_ ? static_cast<ScreenCastPortal*>(portal_.get())
                               : nullptr;
}

}  // namespace webrtc
