#include "MediaControler.h"

#include <iostream>
#include "AudioContext.h"

namespace UkuiAudioFramwork
{
const char* mprisPlayerDestPrefix = "org.mpris.MediaPlayer2";

MediaControler& MediaControler::getInstance()
{
    static MediaControler instance;
    return instance;
}

void MediaControler::pauseAllPlayers()
{
    GError* error = nullptr;
    auto connection = g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, &error);
    if (!connection) {
        AUDIO_ERROR("Failed to get session bus connection: {}.", error->message);
        g_error_free(error);
        return;
    }

    auto playerNames = getMprisPlayers(connection);
    if (playerNames.empty()) {
        AUDIO_ERROR("No MPRIS players found.");
        g_bus_unown_name(g_bus_own_name(G_BUS_TYPE_SESSION, nullptr, G_BUS_NAME_OWNER_FLAGS_NONE, nullptr, nullptr, nullptr, nullptr, nullptr));
        if (error) {
            AUDIO_ERROR("Failed to unown name: {}.", error->message);
            g_error_free(error);
        }
        return;
    }

    AUDIO_DEBUG("Pausing all players.");
    for (const auto& playerName : playerNames) {
        auto playerProxy = g_dbus_proxy_new_sync(connection,
                                                 G_DBUS_PROXY_FLAGS_NONE,
                                                 nullptr,
                                                 playerName.c_str(),
                                                 "/org/mpris/MediaPlayer2",
                                                 "org.mpris.MediaPlayer2.Player",
                                                 nullptr,
                                                 &error);
        if (!playerProxy) {
            AUDIO_ERROR("Failed to create proxy for player: {}, error: {}.", playerName, error->message);
            g_error_free(error);
            continue;
        }

        auto pauseResult = g_dbus_proxy_call_sync(playerProxy,
                                                  "Pause",
                                                  nullptr,
                                                  G_DBUS_CALL_FLAGS_NONE,
                                                  -1,
                                                  nullptr,
                                                  &error);
        if (!pauseResult) {
            AUDIO_ERROR("Failed to pause player:{}, error: {}.", playerName, error->message);
            g_error_free(error);
        } else {
            g_variant_unref(pauseResult);
        }

        g_object_unref(playerProxy);
    }

    g_bus_unown_name(g_bus_own_name(G_BUS_TYPE_SESSION, nullptr, G_BUS_NAME_OWNER_FLAGS_NONE, nullptr, nullptr, nullptr, nullptr, nullptr));
    if (error) {
        AUDIO_ERROR("Failed to unown name: {}.", error->message);
        g_error_free(error);
    }
}

std::vector<std::string> MediaControler::getMprisPlayers(GDBusConnection* connection) const
{
    std::vector<std::string> playerNames;
    GError* error = nullptr;
    GDBusProxy* proxy = g_dbus_proxy_new_sync(connection,
                                              G_DBUS_PROXY_FLAGS_NONE,
                                              nullptr,
                                              "org.freedesktop.DBus",
                                              "/org/freedesktop/DBus",
                                              "org.freedesktop.DBus",
                                              nullptr,
                                              &error);
    if (!proxy) {
        AUDIO_ERROR("Failed to create proxy: {}.", error->message);
        g_error_free(error);
        return playerNames;
    }

    GVariant* result = g_dbus_proxy_call_sync(proxy,
                                              "ListNames",
                                              nullptr,
                                              G_DBUS_CALL_FLAGS_NONE,
                                              -1,
                                              nullptr,
                                              &error);
    if (!result) {
        AUDIO_ERROR("Failed to call ListNames: {}.", error->message);
        g_error_free(error);
    } else {
        GVariantIter* iter;
        const gchar* name;
        g_variant_get(result, "(as)", &iter);
        while (g_variant_iter_loop(iter, "&s", &name)) {
            if (g_str_has_prefix(name, mprisPlayerDestPrefix)) {
                playerNames.push_back(name);
            }
        }
        g_variant_iter_free(iter);
        g_variant_unref(result);
    }

    g_object_unref(proxy);
    return playerNames;
}
}
