/*
  Q Light Controller Plus
  main.cpp

  Copyright (c) Massimo Callegari

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0.txt

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

#include <QSettings>
#include <QApplication>
#include <QSurfaceFormat>
#include <QCommandLineParser>
#include <QQmlApplicationEngine>

#include "app.h"
#include "networkmanager.h"
#include "qlcconfig.h"
#include "qlcfile.h"

QFile logFile;

/**
 * Prints the application version
 */
void printVersion()
{
    QTextStream cout(stdout, QIODevice::WriteOnly);

    cout << Qt::endl;
    cout << APPNAME << " " << "version " << APPVERSION << Qt::endl;
    cout << "This program is licensed under the terms of the ";
    cout << "Apache 2.0 license." << Qt::endl;
    cout << "Copyright (c) Heikki Junnila (hjunnila@users.sf.net)" << Qt::endl;
    cout << "Copyright (c) Massimo Callegari (massimocallegari@yahoo.it)" << Qt::endl;
    cout << Qt::endl;
}

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    // Since Qt6, the default rendering backend is Rhi. 
    // QLC+ doesn't support it yet so OpenGL have to be forced.
    QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGLRhi);
    qputenv("QT3D_RENDERER", "opengl");

    QApplication::setOrganizationName("qlcplus");
    QApplication::setOrganizationDomain("qlcplus.org");
    QApplication::setApplicationName(APPNAME);
    QApplication::setApplicationVersion(QString(APPVERSION));

    printVersion();

    QCommandLineParser parser;
    parser.setApplicationDescription("Q Light Controller Plus");

    parser.addHelpOption();
    parser.addVersionOption();

    QCommandLineOption openFileOption(QStringList() << "o" << "open",
                                      "Specify a file to open.");
    parser.addOption(openFileOption);

    parser.addPositionalArgument("file", "File to open.", "[file]");

    QCommandLineOption openLastOption(QStringList() << "9" << "openlast",
                                      "Open the file from last session.");
    parser.addOption(openLastOption);

    QCommandLineOption fullscreenOption(QStringList() << "f" << "fullscreen",
                                        "Start the application in fullscreen mode");
    parser.addOption(fullscreenOption);

    QCommandLineOption kioskOption(QStringList() << "k" << "kiosk",
                                      "Enable kiosk mode (only Virtual Console)");
    parser.addOption(kioskOption);

    QCommandLineOption localeOption(QStringList() << "l" << "locale",
                                      "Specify a language to use.",
                                      "locale", "");
    parser.addOption(localeOption);

    QCommandLineOption debugOption(QStringList() << "d" << "debug",
                                   "Enable debug messages.");
    parser.addOption(debugOption);

    QCommandLineOption logOption(QStringList() << "g" << "log",
                                   "Log debug messages to a file.");
    parser.addOption(logOption);

    QCommandLineOption threedSupportOption(QStringList() << "3" << "no3d",
                                      "Disable the 3D preview.");
    parser.addOption(threedSupportOption);

    QCommandLineOption noWmOption(QStringList() << "m" << "nowm",
                                  "The OS doesn't provide a window manager");
    parser.addOption(noWmOption);

    QCommandLineOption webAccessOption(QStringList() << "w" << "web",
                                      "Enable remote web access");
    parser.addOption(webAccessOption);

    QCommandLineOption webPortOption(QStringList() << "wp" << "web-port",
                                      "Set the port to use for web access",
                                      "port", "");
    parser.addOption(webPortOption);

    QCommandLineOption webAuthOption(QStringList() << "wa" << "web-auth",
                                      "Enable remote web access with users authentication");
    parser.addOption(webAuthOption);

    QCommandLineOption webAuthFileOption(QStringList() << "a" << "web-auth-file",
                                      "Specify a file where to store web access basic authentication credentials",
                                      "file", "");
    parser.addOption(webAuthFileOption);

    parser.process(app);

    bool enableWebAccess = parser.isSet(webAccessOption)
        || parser.isSet(webPortOption)
        || parser.isSet(webAuthOption)
        || parser.isSet(webAuthFileOption);
    bool enableWebAuth = parser.isSet(webAuthOption);
    int webAccessPort = parser.value(webPortOption).toInt();
    QString webAccessPasswordFile = parser.value(webAuthFileOption);

#if !defined Q_OS_ANDROID
    // 3D enablement
    if (!parser.isSet(threedSupportOption))
    {
        QSurfaceFormat format;
        format.setMajorVersion(3);
        format.setMinorVersion(3);
        format.setProfile(QSurfaceFormat::CoreProfile);
        QSurfaceFormat::setDefaultFormat(format);
    }
#endif

    if (parser.isSet(noWmOption))
        QLCFile::setHasWindowManager(false);

    if (parser.isSet(logOption))
    {
        QString logFilename = QDir::homePath() + QDir::separator() + "QLC+.log";
        logFile.setFileName(logFilename);
        if (!logFile.open(QIODevice::Append))
            qWarning("Warning: Unable to open log file.");
    }

    // logging option
    if (parser.isSet(debugOption))
        qInstallMessageHandler(
            [](QtMsgType, const QMessageLogContext &, const QString &msg) {
                QByteArray localMsg = msg.toLocal8Bit();
                //if (type >= QtSystemMsg)
                {
                    if (logFile.isOpen())
                    {
                        logFile.write(localMsg);
                        logFile.write((char *)"\n");
                        logFile.flush();
                    }

                    fprintf(stderr, "%s\n", localMsg.constData());
                    fflush(stderr);
                }
        });

    // language settings
    QString locale = parser.value(localeOption);

    App qlcplusApp;
    if (locale.isEmpty())
    {
        QSettings settings;
        QVariant language = settings.value(SETTINGS_LANGUAGE);
        if (language.isValid())
            locale = language.toString();
    }
    qlcplusApp.setLanguage(locale);

    if (parser.isSet(threedSupportOption))
        qlcplusApp.set3dSupported(false);

    // kiosk mode
    if (parser.isSet(kioskOption))
        qlcplusApp.enableKioskMode();

    qlcplusApp.startup();

    // open file
    QString filename;
    QStringList posArgs = parser.positionalArguments();
    if (!posArgs.isEmpty())
        filename = posArgs.first();

    if (filename.isEmpty() == false)
    {
        if (filename.endsWith(KExtFixture))
            qlcplusApp.loadFixture(filename);
        else
            qlcplusApp.loadWorkspace(filename);
    }

    // open last file
    if (parser.isSet(openLastOption))
        qlcplusApp.loadLastWorkspace();

    if (enableWebAccess && qlcplusApp.networkManager() != nullptr)
    {
        qlcplusApp.networkManager()->setWebServerConfiguration(webAccessPort, enableWebAuth,
                                                               webAccessPasswordFile);
        qlcplusApp.networkManager()->setServerType(NetworkManager::WebServer);
        if (qlcplusApp.networkManager()->serverStarted() == false)
            qlcplusApp.networkManager()->startServer();
    }

    // fullscreen mode
    if (parser.isSet(fullscreenOption))
        qlcplusApp.toggleFullscreen();

    return app.exec();
}
