/*
 * Copyright (C) 2020, 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 "cmainwnd.h"
#include "texteditmenuprovider.h"
#include "global/kaglobal.h"

#include <QApplication>
#include <QFileInfo>
#include <QDir>
#include <QTranslator>
#include <QLibraryInfo>
#include <QWidget>
#include <QCommandLineParser>
#include <QScreen>
#include <QDir>
#include <QQmlApplicationEngine>
#include <QSqlDatabase>
#include <QSqlError>
#include <QStandardPaths>
#include <QtQml>
#include <QSessionManager>
#include <QtQuickControls2/QtQuickControls2>
#include <QElapsedTimer>

#include <windowmanager/windowmanager.h>
#include <kylin-ai/common/common.h>
#include <aiservicedialog.h>
#include <singleapplication.h>

const QString CONFIGPATH = "/.config/kylin-aiassistant/kylin-aiassistant.conf";
const QString BOOTCMDLINE = "/proc/cmdline";
const QString INSTALLEREXITSCOMMAND = " ps aux |grep kylin-os-installer | grep -v grep";
QStringList translationsPaths() {
    QString binaryPath = QFileInfo(qApp->applicationDirPath())
            .absoluteFilePath();

    QString trPath = QDir::toNativeSeparators(binaryPath + "/translations") ;
#if defined(Q_OS_LINUX) || defined(Q_OS_UNIX)
    return QStringList()
            << QStringLiteral(APP_PREFIX) + "/share/kylin-aiassistant/translations"
            << trPath
            << QStringLiteral("/usr/share/kylin-aiassistant/translations")
            << QStringLiteral("/usr/local/share/kylin-aiassistant/translations");
#elif defined(Q_OS_WIN)
    return QStringList()
            << trPath;
#endif
}

bool isContainsLive(){
    // 打开/proc/cmdline文件
    QFile file(BOOTCMDLINE);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        return false;
    }
    // 读取文件内容
    QTextStream in(&file);
    QString content = in.readAll();
    file.close();
    // 使用正则表达式精确匹配完整参数，避免部分匹配
    // 匹配规则：参数前后为空格或字符串开头/结尾
    QRegularExpression regex(QStringLiteral("(^|\\s)%1(\\s|$)").arg(QRegularExpression::escape("boot=casper")));
    bool isExit = regex.match(content).hasMatch();
    KyInfo() << "当前/proc/cmdline中是否存在boot=casper字段" << isExit;
    return isExit;
}

bool isKylinInstallerRunning(){
    QProcess process;
    // 执行命令，使用/bin/sh解析管道等特殊符号
    process.start("/bin/sh", QStringList() << "-c" << INSTALLEREXITSCOMMAND);
    // 等待命令执行完成，超时时间设置为3秒
    process.waitForFinished(3000);

    // 读取标准输出和标准错误
    QString output = process.readAllStandardOutput();
    QString error = process.readAllStandardError();

    // 如果有错误信息，将错误信息也包含到结果中
    if (!error.isEmpty()) {
        output += "\nError: " + error;
    }
    KyInfo() << "current is Installer exits result:" << output;
    return !output.trimmed().isEmpty();
}


static void initDataDir()
{
    QString confFile = QDir::homePath() + CONFIGPATH;
    QSettings settings(confFile, QSettings::IniFormat);
    settings.setIniCodec("utf8");

    QString storedDirPath = settings.value("directories/baseDir", "").toString();

    QString dirPath;
    if (storedDirPath.isEmpty()) {
        // 使用默认路径
        QString docPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
        dirPath = docPath + "/kylin-aiassistant";

        settings.setValue("directories/baseDir", dirPath);
        KyInfo() << "使用默认路径" << dirPath;
    } else {
        // 使用存储的路径
        dirPath = storedDirPath;
        KyInfo() << "使用存储的路径" << dirPath;
    }

    QDir dir;
    if (!dir.exists(dirPath)) {
        if (!dir.mkpath(dirPath)) {
            KyInfo() << "创建助手目录失败";
            return;
        } else {
            KyInfo() << "创建助手目录成功 dirPath === " << dirPath;
        }
    }
    Globals::defaultPath = dirPath;

    QString readPath = dirPath + "/.read";
    if (!dir.exists(readPath)) {
        if (!dir.mkpath(readPath)) {
            KyInfo() << "创建朗读目录失败";
            return;
        } else {
            KyInfo() << "创建朗读目录成功 dirPath === " << readPath;
        }
    }

    KyInfo() << "所有文件和目录初始化成功";
    return;
}

int main(int argc, char *argv[])
{
    QElapsedTimer allTimer;
    QElapsedTimer t;
    allTimer.start();
    t.start();
//#ifndef QT_DEBUG
//    initUkuiLog4qt("kylin-aiassistant");
//#endif

    qRegisterMetaType<QMap<int,QString>>("QMap<int,QString>");
    qmlRegisterType<TextEditMenuProvider>("TextEditMenu", 1, 0, "TextEditMenuProvider");
    qInfo() << "******* qml 注册耗时：" << t.elapsed();
    t.start();

    //wayland适配
    QString env = qgetenv("XDG_SESSION_TYPE");
    if(env == "wayland"){
        //qputenv("QT_QPA_PLATFORM","xcb");
        isWayland = true;

    }

// 修改分辨率的显示
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 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

    qInfo() << "******* 显示适配耗时：" << t.elapsed();
    t.start();

    QtSingleApplication app("aiassistant", argc, argv);
    app.setApplicationName("kylin-aiassistant");
    // AI助手不跟随主题切换，只采用浅色主题
    qApp->setProperty("useLightTheme", true);
    qApp->setStyle("ukui");
    // 发言人重命名后报错 QQuickWidget cannot be used as a native child widget. Consider setting Qt::AA_DontCreateNativeWidgetSiblings
    app.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);

    qInfo() << "******* app构造耗时：" << t.elapsed();
    t.start();

    QCommandLineParser parser;
    parser.setApplicationDescription("kylin-aiassistant");
    parser.addHelpOption();

    QCommandLineOption silenceOption(QStringList() << "s" << "silence",
            QCoreApplication::translate("main", "Start silently."));
    QCommandLineOption selectedOption(QStringList() << "l" << "selected",
            QCoreApplication::translate("main", "Start with selected words."));
    QCommandLineOption fileOption(QStringList() << "f" << "file",
                QCoreApplication::translate("main", "Start with send file."));

    parser.addOption(silenceOption);
    parser.addOption(selectedOption);
    parser.addOption(fileOption);
    parser.process(app);
    const QStringList args = parser.positionalArguments();

    bool silence = parser.isSet(silenceOption);
    bool selected = parser.isSet(selectedOption);
    bool isFile = parser.isSet(fileOption);

    if (app.isRunning()) {
        if (selected){
            app.sendMessage("selected", 1000);
        } else if (isFile) {
            app.sendMessage(args.first(), 1000);
        } else if (!silence) {
            // 非首次启动行为为激活AI助手，弹出AI助手的UI界面
            app.sendMessage("running" , 4000);
        }

        return 0;
    }
    qInfo() << "******* 命令行参数解析耗时：" << t.elapsed();
    t.start();

    /* 加载翻译文件 */
    QString kylinAiAssistantTransPath = "/usr/share/kylin-aiassistant/translations";
    QString qtTransPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
    QString locale = QLocale::system().name();

    KyInfo()<<"kylinAiAssistantTransPath"<<kylinAiAssistantTransPath;
    KyInfo()<<"qtTransPath"<<qtTransPath;
    KyInfo()<<"locale"<<locale;

    QTranslator trans_global , trans_qt;
    QTranslator trans_SDK;

    if (!trans_global.load(QLocale(), "Internationalization", "_", kylinAiAssistantTransPath)) {
        KyInfo() << "Load global translations file" <<QLocale() << "failed!";
    } else {
        app.installTranslator(&trans_global);
        KyInfo()<<"success!";
    }

    if (!trans_qt.load(QLocale(), "qt", "_", qtTransPath)) {
        KyInfo() << "Load qt translations file" <<QLocale() << "failed!";
    } else {
        app.installTranslator(&trans_qt);
    }

    QString path = QString(":/translations/gui_%1.qm").arg(locale);
    if (trans_SDK.load(path)) {
        app.installTranslator(&trans_SDK);
    }

    qInfo() << "******* 加载翻译耗时：" << t.elapsed();
    t.start();

    initDataDir();
    qInfo() << "******* 创建Data目录耗时：" << t.elapsed();
    t.start();

    //试用模式下助手不启动
    if(isContainsLive() || isKylinInstallerRunning()){
        return 0;
    }
    qInfo() << "******* 试用模式不启动判断耗时：" << t.elapsed();
    t.start();
    CMainWnd wnd;

    qInfo() << "******* 构造cmainwnd耗时：" << t.elapsed();
    t.start();
    // 需要设置焦点窗口，这样再次启动的时候激活该窗口
    app.setActivationWindow(&wnd);

    // 非首次启动行为为激活AI助手，弹出AI助手的UI界面
    QObject::connect(&app, &QtSingleApplication::messageReceived, &wnd, &CMainWnd::onAppRestarted);
    QObject::connect(&app, &QtSingleApplication::aboutToQuit, &wnd, &CMainWnd::aboutToQuit);

    qInfo() << "******* 处理槽函数耗时：" << t.elapsed();
    t.start();

    if (!silence) {
        wnd.show();
    }

    qInfo() << "******* 处理show耗时：" << t.elapsed();

    QTimer::singleShot(10, [&]() {
            t.start();
            wnd.initComponent();
            if (!silence) {
                wnd.showView();
            }
            qInfo() << "******* 处理组件化耗时：" << t.elapsed();
            t.start();

            //如果AI助手未启动，收到右键发送的文件，在这里处理
            if (isFile) {
                wnd.onAppRestarted(args.first());
            }
            qInfo() << "******* 处理发送文件耗时：" << t.elapsed();
    });

    qInfo() << "**** main.cpp 执行时间" << allTimer.elapsed();

    return app.exec();
}
