/*
 * Copyright (C) 2016 Canonical Ltd.
 * Copyright (C) 2026 UBports Foundation.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * 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 <lomiri/storage/provider/Server.h>

#include "RcloneProvider.h"

#include <QCoreApplication>
#include <QSocketNotifier>

#include <cerrno>
#include <csignal>
#include <cstdio>
#include <cstring>
#include <print>
#include <sys/socket.h>
#include <unistd.h>

using namespace std;
using namespace lomiri::storage::provider;

namespace
{

// Handle SIGTERM and SIGINT for proper rclone daemon cleanup.
// See: https://doc.qt.io/archives/qt-5.15/unix-signals.html
int signal_fd[2] = {-1, -1};

void handle_unix_signal(int)
{
    char c = 1;
    std::ignore = ::write(signal_fd[1], &c, 1);
}

void install_signal_handlers()
{
    if (::socketpair(AF_UNIX, SOCK_STREAM, 0, signal_fd) != 0)
        qFatal("Couldn't create signal socketpair: %s", strerror(errno));

    auto* notifier = new QSocketNotifier(signal_fd[0], QSocketNotifier::Read);
    QObject::connect(notifier, &QSocketNotifier::activated,
                     [] { QCoreApplication::quit(); });

    struct sigaction sa;
    sa.sa_handler = handle_unix_signal;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    sa.sa_flags |= SA_RESTART;
    sigaction(SIGTERM, &sa, nullptr);
    sigaction(SIGINT, &sa, nullptr);
}

}  // namespace

int main(int argc, char** argv)
{
    string const bus_name = "com.lomiri.StorageFramework.Provider.Rclone";
    string const account_service_id = "";

    try
    {
        Server<RcloneProvider> server(bus_name, account_service_id);
        server.init(argc, argv);
        install_signal_handlers();
        return server.run();
    }
    catch (std::exception const& e)
    {
        std::println(stderr, "lomiri-storage-provider-rclone: {}", e.what());
        return 1;
    }
}
