/*
 *  Copyright 2022 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/screen_capture_portal_interface.h"
#include "modules/desktop_capture/linux/wayland/xdg_desktop_portal_utils.h"

#include <string>

#include "rtc_base/logging.h"

namespace webrtc {
namespace xdg_portal {

void ScreenCapturePortalInterface::RequestSessionUsingProxy(
    GAsyncResult* result) {
  Scoped<GError> error;
  GDBusProxy* proxy = g_dbus_proxy_new_finish(result, error.receive());
  if (!proxy) {
    // Ignore the error caused by user cancelling the request via `cancellable_`
    if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED))
      return;
    RTC_LOG(LS_ERROR) << "Failed to get a proxy for the portal: "
                      << error->message;
    OnPortalDone(RequestResponse::kError);
    return;
  }

  RTC_LOG(LS_INFO) << "Successfully created proxy for the portal.";
  RequestSession(proxy);
}

void ScreenCapturePortalInterface::OnSessionRequestResult(
    GDBusProxy* proxy,
    GAsyncResult* result) {
  Scoped<GError> error;
  Scoped<GVariant> variant(
      g_dbus_proxy_call_finish(proxy, result, error.receive()));
  if (!variant) {
    // Ignore the error caused by user cancelling the request via `cancellable_`
    if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED))
      return;
    RTC_LOG(LS_ERROR) << "Failed to request session: " << error->message;
    OnPortalDone(RequestResponse::kError);
    return;
  }

  RTC_LOG(LS_INFO) << "Initializing the session.";

  Scoped<char> handle;
  g_variant_get_child(variant.get(), /*index=*/0, /*format_string=*/"o",
                      &handle);
  if (!handle) {
    RTC_LOG(LS_ERROR) << "Failed to initialize the session.";
    OnPortalDone(RequestResponse::kError);
    return;
  }
}

void ScreenCapturePortalInterface::RegisterSessionClosedSignalHandler(
    const SessionClosedSignalHandler session_close_signal_handler,
    GVariant* parameters,
    GDBusConnection* connection,
    std::string& session_handle,
    guint& session_closed_signal_id) {
  uint32_t portal_response = 2;
  Scoped<GVariant> response_data;
  g_variant_get(parameters, /*format_string=*/"(u@a{sv})", &portal_response,
                response_data.receive());

  if (RequestResponseFromPortalResponse(portal_response) !=
      RequestResponse::kSuccess) {
    RTC_LOG(LS_ERROR) << "Failed to request the session subscription.";
    OnPortalDone(RequestResponse::kError);
    return;
  }

  Scoped<GVariant> g_session_handle(
      g_variant_lookup_value(response_data.get(), /*key=*/"session_handle",
                             /*expected_type=*/nullptr));
  session_handle = g_variant_get_string(
      /*value=*/g_session_handle.get(), /*length=*/nullptr);

  if (session_handle.empty()) {
    RTC_LOG(LS_ERROR) << "Could not get session handle despite valid response";
    OnPortalDone(RequestResponse::kError);
    return;
  }

  session_closed_signal_id = g_dbus_connection_signal_subscribe(
      connection, kDesktopBusName, kSessionInterfaceName, /*member=*/"Closed",
      session_handle.c_str(), /*arg0=*/nullptr, G_DBUS_SIGNAL_FLAGS_NONE,
      session_close_signal_handler, this, /*user_data_free_func=*/nullptr);
}

void ScreenCapturePortalInterface::OnStartRequestResult(GDBusProxy* proxy,
                                                        GAsyncResult* result) {
  Scoped<GError> error;
  Scoped<GVariant> variant(
      g_dbus_proxy_call_finish(proxy, result, error.receive()));
  if (!variant) {
    if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED))
      return;
    RTC_LOG(LS_ERROR) << "Failed to start the portal session: "
                      << error->message;
    OnPortalDone(RequestResponse::kError);
    return;
  }

  Scoped<char> handle;
  g_variant_get_child(variant.get(), 0, "o", handle.receive());
  if (!handle) {
    RTC_LOG(LS_ERROR) << "Failed to initialize the start portal session.";
    OnPortalDone(RequestResponse::kError);
    return;
  }

  RTC_LOG(LS_INFO) << "Subscribed to the start signal.";
}

}  // namespace xdg_portal
}  // namespace webrtc
