/*
* Copyright (C) 2025, 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
 * (at your option) 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 <https://www.gnu.org/licenses/>.
 *
 * Authors: iaom <zhangpengfei@kylinos.cn>
 *
 */

#include "dbus-connector.h"

#include <QCoreApplication>
#include <QTime>
#include <QDebug>
#include <QDBusServiceWatcher>

namespace UkuiQuick {
class DbusConnectorPrivate
{
public:
    DbusConnectorPrivate(const QString& service
                         , const QString& path
                         , const QString& interface
                         , QDBusConnection conn)
        : m_service(service)
        , m_path(path)
        , m_interface(interface)
        , m_conn(std::move(conn))
    {
    }
    QString m_service;
    QString m_path;
    QString m_interface;
    QDBusConnection m_conn;
};

DbusConnector::DbusConnector(const QString &service, const QString& path, const QString& interface, QDBusConnection conn, QObject* parent)
    : QThread(parent), d(new DbusConnectorPrivate(service, path, interface, conn))
{
}

DbusConnector::~DbusConnector()
{
    quit();
    wait();
    if (d) {
        delete d;
        d = nullptr;
    }
}

void DbusConnector::run()
{
    auto createAndValidateInterface = [this]() -> QDBusInterface* {
        auto dbus(new QDBusInterface(d->m_service, d->m_path, d->m_interface, d->m_conn));
        if (dbus->isValid()) {
            qWarning() << "DbusConnector: dbus connection success!";
            dbus->moveToThread(QCoreApplication::instance()->thread());
            return dbus;
        }
        qWarning() << "DBus connection failed:" << dbus->lastError().message();
        delete dbus;
        return nullptr;
    };

    qDebug() << "DbusConnector begin init dbus interface" << d->m_service << d->m_path << d->m_interface;
    if (auto dbus = createAndValidateInterface()) {
        Q_EMIT ready(dbus);
        return;
    }

    auto watcher = new QDBusServiceWatcher(d->m_service, d->m_conn, QDBusServiceWatcher::WatchForRegistration);
    connect(watcher, &QDBusServiceWatcher::serviceRegistered, this, [this, createAndValidateInterface]() {
        qDebug() << "DbusConnector: service registered, begin init dbus interface" << d->m_service << d->m_path << d->m_interface;
        if (auto dbus = createAndValidateInterface()) {
            Q_EMIT ready(dbus);
        }
        sender()->deleteLater();
        this->quit();
    });
    exec();
}
}