/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*-
 * -*- coding: utf-8 -*-
 *
 * Copyright (C) 2024 KylinSoft Co., Ltd.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "audio.h"
#include "audio_define.h"

Audio::Audio(QObject *parent):
    QObject(parent)
{
    qInfo() << "Initializing Audio";
    initSignals();
}

Audio::~Audio()
{

}

void Audio::initSignals()
{
    QDBusConnection::sessionBus().connect(UKUI_MEDIA_SERVICE,
                                          UKUI_MEDIA_CONTROL_PATH,
                                          QString(),
                                          "updateVolume",
                                          this,
                                          SIGNAL(SinkVolumeChanged(int)));

    QDBusConnection::sessionBus().connect(UKUI_MEDIA_SERVICE,
                                          UKUI_MEDIA_CONTROL_PATH,
                                          QString(),
                                          "updateMute",
                                          this,
                                          SIGNAL(SinkMuteChanged(bool)));

    QDBusConnection::sessionBus().connect(UKUI_MEDIA_SERVICE,
                                          UKUI_MEDIA_CONTROL_PATH,
                                          QString(),
                                          "updateDevice",
                                          this,
                                          SIGNAL(SinkDeviceChanged(QString)));

    QDBusConnection::sessionBus().connect(UKUI_MEDIA_SERVICE,
                                          UKUI_MEDIA_CONTROL_PATH,
                                          QString(),
                                          "updateSourceVolume",
                                          this,
                                          SIGNAL(SourceVolumeChanged(int)));

    QDBusConnection::sessionBus().connect(UKUI_MEDIA_SERVICE,
                                          UKUI_MEDIA_CONTROL_PATH,
                                          QString(),
                                          "updateSourceMute",
                                          this,
                                          SIGNAL(SourceMuteChanged(bool)));

    QDBusConnection::sessionBus().connect(UKUI_MEDIA_SERVICE,
                                          UKUI_MEDIA_CONTROL_PATH,
                                          QString(),
                                          "updateSourceDevice",
                                          this,
                                          SIGNAL(SourceDeviceChanged(QString)));
}

int Audio::GetSinkVolume()
{
    QDBusReply<int> reply = callMedia("getDefaultOutputVolume");

    if (!reply.isValid()) {
        qWarning() << "Failed to get default output volume.";
        return -1;
    }
    this->sinkVolume = reply.value();

    return this->sinkVolume;
}

bool Audio::GetSinkMute()
{
    QDBusReply<bool> reply = callMedia("getDefaultOutputMuteState");

    if (!reply.isValid()) {
        qWarning() << "Failed to get output mute state.";
        return false;
    }
    this->sinkMute = reply.value();

    return this->sinkMute;
}

QString Audio::GetSinkDevice()
{
    QDBusReply<QString> reply = callMedia("getDefaultOutputDevice");

    if (!reply.isValid()) {
        qWarning() << "Failed to get output device.";
        return "NULL";
    }
    this->sinkDevice = reply.value();

    return this->sinkDevice;
}

int Audio::GetSourceVolume()
{
    QDBusReply<int> reply = callMedia("getDefaultInputVolume");

    if (!reply.isValid()) {
        qWarning() << "Failed to get output mute state.";
        return -1;
    }
    this->sourceVolume = reply.value();

    return this->sourceVolume;
}

bool Audio::GetSourceMute()
{
    QDBusReply<bool> reply = callMedia("getDefaultInputMuteState");

    if (!reply.isValid()) {
        qWarning() << "Failed to get input mute state.";
        return false;
    }
    this->sourceMute = reply.value();

    return this->sourceMute;
}

QString Audio::GetSourceDevice()
{
    QDBusReply<QString> reply = callMedia("getDefaultInputDevice");

    if (!reply.isValid()) {
        qWarning() << "Failed to get input device.";
        return "NULL";
    }
    this->sourceDevice = reply.value();

    return this->sourceDevice;
}

bool Audio::SetSinkVolume(int volume)
{
    QDBusReply<bool> reply = callMedia("setDefaultOutputVolume", volume);

    if (!reply.isValid()) {
        qWarning() << "Failed to set output volume to" << volume;
        return false;
    }

    return reply.value();
}

bool Audio::SetSinkMute(bool mute)
{
    QDBusReply<bool> reply = callMedia("setDefaultOutputMuteState", mute);

    if (!reply.isValid()) {
        qWarning() << "Failed to set output mute state to" << mute;
        return false;
    }

    return reply.value();
}

bool Audio::SetSinkDevice(QString device)
{
    QDBusReply<bool> reply = callMedia("setDefaultOutputDevice", device);

    if (!reply.isValid()) {
        qWarning() << "Failed to set outputdevice to" << device;
        return false;
    }

    return reply.value();
}

bool Audio::SetSourceVolume(int volume)
{
    QDBusReply<bool> reply = callMedia("setDefaultInputVolume", volume);

    if (!reply.isValid()) {
        qWarning() << "Failed to set input volume to" << volume;
        return false;
    }

    return reply.value();
}

bool Audio::SetSourceMute(bool mute)
{
    QDBusReply<bool> reply = callMedia("setDefaultInputMuteState", mute);

    if (!reply.isValid()) {
        qWarning() << "Failed to set input mute state to" << mute;
        return false;
    }

    return reply.value();
}

bool Audio::SetSourceDevice(QString device)
{
    QDBusReply<bool> reply = callMedia("setDefaultInputDevice", device);

    if (!reply.isValid()) {
        qWarning() << "Failed to set inputdevice to" << device;
        return false;
    }

    return reply.value();
}


QDBusMessage Audio::callMedia(const QString &method, const QVariant &arg1, const QVariant &arg2)
{
    QDBusInterface mediaInterface(UKUI_MEDIA_SERVICE,
                                   UKUI_MEDIA_PATH,
                                   UKUI_MEDIA_INTERFACE);

    return mediaInterface.call(method, arg1, arg2);
}

