/*
 * Copyright (C) 2023 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/>.
 */
#include "clock.h"
#include "singleApplication.h"
#include <QApplication>
#include <QDesktopWidget>
#include <X11/Xlib.h>
#include "xatom-helper.h"
#include <ukui-log4qt.h>
#include "gsettingsubject.h"
#include "clockdbusadaptor.h"
#include "dbusupdateclockadaptor.h"
#include "dbusdeleteclockbyidadaptor.h"
#include "dbusselectclockbyidadaptor.h"
#include "ClockInterface.h"
#include <QDBusMetaType>
/*!
 * \brief myMessageOutput
 * 日志打印输出
 */
void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    // 加锁
    static QMutex mutex;
    mutex.lock();
    qDebug()<<msg;
    QByteArray localMsg = msg.toLocal8Bit();

    QString strMsg("");
    switch (type) {
    case QtDebugMsg:
        strMsg = QString("Debug    ");
        break;
    case QtWarningMsg:
        strMsg = QString("Warning    ");
        break;
    case QtCriticalMsg:
        strMsg = QString("Critical    ");
        break;
    case QtFatalMsg:
        strMsg = QString("Fatal    ");
        break;
    case QtInfoMsg:
        strMsg = QString("Info    ");
        break;
    }

    // 设置输出信息格式
    QString strDateTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss ddd");
    QString strMessage = QString("[DateTime]: %1  [Message]: %2  [Line]: %3  [Function]: %4")
                         .arg(strDateTime).arg(localMsg.constData()).arg(context.line).arg(
        context.function);

    QString dirStr = QStandardPaths::writableLocation(QStandardPaths::HomeLocation)
                     + "/.config/kylin-clock/";
    QDir dir;
    if (!dir.exists(dirStr)) {
        dir.mkpath(dirStr);
    }
    // 输出信息至文件中（读写、追加形式）
    QString url_filepath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation)
                           + "/.config/kylin-clock/output.log";
    QFile file(url_filepath);

    file.open(QIODevice::ReadWrite | QIODevice::Append);
    QTextStream stream(&file);
    stream << strMsg << strMessage << "\r\n";
    file.flush();
    file.close();

    // 解锁
    mutex.unlock();
}

void publishDbusInterface(Clock * currentClock,QObject * obj){
    //新增
    ClockDbusAdaptor *adaptor = new ClockDbusAdaptor(obj,currentClock);
    //注册接口
    QDBusConnection::sessionBus().registerObject(CLOCK_DBUS_SERVICE_PATH, obj);
    //判断是否注册成功
    if (!QDBusConnection::sessionBus().registerService(CLOCK_DBUS_SERVICE_NAME)) {
        qCritical()<<"注册接口失败"<<QDBusConnection::sessionBus().lastError().message();
        exit(1);
    }
    Q_UNUSED(adaptor);
}
void publishDbusUpdateClock(Clock * currentClock,QObject * obj){
    DbusUpdateClockAdaptor *adaptor = new DbusUpdateClockAdaptor(obj,currentClock);
    //注册接口
    QDBusConnection::sessionBus().registerObject(CLOCK_DBUS_UPDATE_CLOCK_BY_ID_PATH, obj);
    //判断是否注册成功
    if (!QDBusConnection::sessionBus().registerService(CLOCK_DBUS_SERVICE_NAME)) {
        qCritical()<<"注册接口失败"<<QDBusConnection::sessionBus().lastError().message();
        exit(1);
    }
    Q_UNUSED(adaptor);
}
void publishDbusSelectClock(Clock * currentClock,QObject * obj){
    DbusSelectClockByIdAdaptor *adaptor = new DbusSelectClockByIdAdaptor(obj,currentClock);
    //注册接口
    QDBusConnection::sessionBus().registerObject(CLOCK_DBUS_SELECT_CLOCK_BY_ID_PATH, obj);
    //判断是否注册成功
    if (!QDBusConnection::sessionBus().registerService(CLOCK_DBUS_SERVICE_NAME)) {
        qCritical()<<"注册接口失败"<<QDBusConnection::sessionBus().lastError().message();
        exit(1);
    }
    Q_UNUSED(adaptor);
}
void publishDbusDeleteClock(Clock * currentClock,QObject * obj){
    DbusDeleteClockByIdAdaptor *adaptor = new DbusDeleteClockByIdAdaptor(obj,currentClock);
    //注册接口
    QDBusConnection::sessionBus().registerObject(CLOCK_DBUS_DELETE_CLOCK_BY_ID_PATH, obj);
    //判断是否注册成功
    if (!QDBusConnection::sessionBus().registerService(CLOCK_DBUS_SERVICE_NAME)) {
        qCritical()<<"注册接口失败"<<QDBusConnection::sessionBus().lastError().message();
        exit(1);
    }
    Q_UNUSED(adaptor);
}

int main(int argc, char *argv[])
{
    //实例化日志
//    qInstallMessageHandler(myMessageOutput);
    initUkuiLog4qt(APPLICATION_NAME);
    //适配分数缩放
    #if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
        QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
        QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
    #endif
    #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
        QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
    #endif
    //构造单例 利用本地连接qlocalsocket作为判断的公共访问资源
    SingleApplication a(argc, argv);
    //支持主题框架图标
     a.setWindowIcon(QIcon::fromTheme("kylin-alarm-clock"));
    //此属性保存关闭最后一个窗口时应用程序是否隐式退出。默认值为true。
    a.setQuitOnLastWindowClosed(false);


    //如果没在运行
    if (!a.isRunning()) {
        Clock w;
        a.w = &w;
        w.setAttribute(Qt::WA_AlwaysShowToolTips);
        //发布dbus接口
        QObject  obj;
        publishDbusInterface(&w,&obj);
        QObject  updateObj;
        publishDbusUpdateClock(&w,&updateObj);
        QObject  deleteObj;
        publishDbusDeleteClock(&w,&deleteObj);
        QObject  selectObj;
        publishDbusSelectClock(&w,&selectObj);
        // 添加窗管协议。显示的位置
//        XAtomHelper::setStandardWindowHint(w.winId());
//        w.show();
        w.showThisWindow();
        return a.exec();
    }
    return 0;
}
