/*
 * Copyright (C) 2023 ~ 2023 Deepin Technology Co., Ltd.
 *
 * Author:     zhangyu <zhangyud@uniontech.com>
 *
 * Maintainer: zhangyu <zhangyud@uniontech.com>
 *
 * 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 "deepinwatermarkdbus.h"
#include <dlfcn.h>
#include <QDBusConnection>
#include <QDBusMessage>
#include <QDBusConnectionInterface>
#include <QtConcurrent>

DeepinWatermarkDbus::DeepinWatermarkDbus()
{
    loadWaterMarkSo();
}

DeepinWatermarkDbus::~DeepinWatermarkDbus()
{
}

void DeepinWatermarkDbus::loadWaterMarkSo()
{
    if (handle == nullptr) {
        handle = dlopen("libdtkwatermark.so", RTLD_LAZY | RTLD_LOCAL);
        if (handle) {
            void (*loadSM)();
            loadSM = (void(*)())dlsym(handle, "LoadScreenMark");
            loadSM();
        }
    }
}

void DeepinWatermarkDbus::freeWaterMarkSo()
{
    if (handle) {
        void (*freeSM)();
        freeSM = (void(*)())dlsym(handle, "FreeScreenMark");
        freeSM();
        dlclose(handle);
        handle = nullptr;
    }
    invokerPid = 0;
}

void DeepinWatermarkDbus::setScreenWatermark(const QString &strPolicy)
{
    uint invokerPid = connection().interface()->servicePid(message().service());
    loadWaterMarkSo();
    if (handle) {
        bool (*accessible)(const int);
        accessible = (bool(*)(const int))dlsym(handle, "IsAccessible");
        bool flag = accessible(invokerPid);
        if (!flag)
            return;

        void (*setSM)(const char *);
        setSM = (void(*)(const char *))dlsym(handle, "SetScreenWaterMark");
        setSM(strPolicy.toStdString().c_str());

        bool (*getStatus)();
        getStatus = (bool(*)())dlsym(handle, "GetScreenMarkStatus");
        if (getStatus())
            QtConcurrent::run(this, &DeepinWatermarkDbus::setStartUpStatus, true);
    }
}

bool DeepinWatermarkDbus::watermarkStatus()
{
    bool flag = false;
    if (handle) {
        bool (*getStatus)();
        getStatus = (bool(*)())dlsym(handle, "GetScreenMarkStatus");
        flag = getStatus();
    }
    return flag;
}

void DeepinWatermarkDbus::freeScreenWatermark()
{
    uint invokerPid = connection().interface()->servicePid(message().service());
    if (handle) {
        bool (*accessible)(const int);
        accessible = (bool(*)(const int))dlsym(handle, "IsAccessible");
        bool flag = accessible(invokerPid);
        if (!flag)
            return;
    }
    QtConcurrent::run(this, &DeepinWatermarkDbus::setStartUpStatus, false);
    freeWaterMarkSo();
}

void DeepinWatermarkDbus::setStartUpStatus(bool flag)
{
    QString cmd("/usr/bin/systemctl ");
    if (flag)
        cmd += "enable";
    else
        cmd += "disable";
    cmd += " --user deepin-watermark.service";

    system(cmd.toStdString().c_str());
}