/********************************************************************************************
    begin                : sam jui 13 09:50:06 CEST 2002
    copyright            : (C) 2002 - 2003 by Pascal Brachet
                               2003 - 2005 by Jeroen Wijnhout (Jeroen.Wijnhout@kdemail.net)
                               2011 - 2018 by Michel Ludwig (michel.ludwig@kdemail.net)
 ********************************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include <QApplication>
#include <QCommandLineParser>
#include <QCommandLineOption>
#include <QDBusConnectionInterface>
#include <QDBusInterface>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QTextCodec>
#include <QUrl>

#include <KAboutData>
#include <KCrash>
#include <KDBusService>
#include <KEncodingProber>
#include <KLocalizedString>
#include <KMessageBox>

#include "kile.h"
#include "kileversion.h"
#include "kiledebug.h"
#include "kileviewmanager.h"

Q_LOGGING_CATEGORY(LOG_KILE_MAIN, "org.kde.kile.main", QtWarningMsg)
Q_LOGGING_CATEGORY(LOG_KILE_PARSER, "org.kde.kile.parser", QtWarningMsg)
Q_LOGGING_CATEGORY(LOG_KILE_CODECOMPLETION, "org.kde.kile.codecompletion", QtWarningMsg)

bool isProject(const QUrl url)
{
    return url.fileName().endsWith(QLatin1String(".kilepr"));
}

QString readDataFromStdin()
{
    KILE_DEBUG_MAIN;

    QByteArray fileData;
    QFile qstdin;

    qstdin.open( stdin, QIODevice::ReadOnly );
    fileData = qstdin.readAll();
    qstdin.close();

    QTemporaryDir *tempDir = new QTemporaryDir(QDir::tempPath() + QLatin1Char('/') + QStringLiteral("kile-stdin"));
    QString tempFileName = QFileInfo(tempDir->path(), i18n("StandardInput.tex")).absoluteFilePath();
    KILE_DEBUG_MAIN << "tempFile is " << tempFileName;

    QFile tempFile(tempFileName);
    if(!tempFile.open(QIODevice::WriteOnly)) {
        return QString();
    }

    QTextStream stream(&tempFile);

    KEncodingProber prober(KEncodingProber::Universal);
    KEncodingProber::ProberState state = prober.feed(fileData);
    KILE_DEBUG_MAIN << "KEncodingProber::state " << state;
    KILE_DEBUG_MAIN << "KEncodingProber::prober.confidence() " << prober.confidence();
    KILE_DEBUG_MAIN << "KEncodingProber::encoding " << prober.encoding();

    auto encoding = QStringEncoder::encodingForName(prober.encoding());
    if(encoding) {
        stream.setEncoding(*encoding);
    }

    stream << fileData;
    tempFile.close();

    return tempFileName;
}

inline void initQtResources() {
    Q_INIT_RESOURCE(kile);
}

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

    initQtResources();

    app.setApplicationName(QStringLiteral("kile"));
    KLocalizedString::setApplicationDomain("kile");

    KAboutData aboutData(QStringLiteral("kile"), i18n("Kile"), QLatin1StringView(KILE_VERSION_STRING),
                         i18n("KDE Integrated LaTeX Environment"),
                         KAboutLicense::GPL,
                         i18nc("the parameter is the last copyright year", "by the Kile Team (2003 - %1)", QStringLiteral(KILE_LAST_COPYRIGHT_YEAR)),
                         QString(),
                         QStringLiteral("https://kile.sourceforge.io"));
    aboutData.addAuthor(i18n("Michel Ludwig"), i18n("Project Management/Developer"), QStringLiteral("michel.ludwig@kdemail.net"));
    aboutData.addAuthor(i18n("Holger Danielsson"), i18n("Developer"), QStringLiteral("holger.danielsson@versanet.de"));
    aboutData.addAuthor(i18n("Thomas Braun"), i18n("Former Developer"), QStringLiteral("thomas.braun@virtuell-zuhause.de"));
    aboutData.addAuthor(i18n("Jeroen Wijnhout"), i18n("Former Maintainer/Developer"), QStringLiteral("Jeroen.Wijnhout@kdemail.net"));
    aboutData.addAuthor(i18n("Brachet Pascal"));

    aboutData.addCredit(i18n("Andrius Štikonas"), i18n("Migration from Subversion to Git"), QStringLiteral("andrius@stikonas.eu"));
    aboutData.addCredit(i18n("Simon Martin"), i18n("KConfig XT, Various Improvements and Bug-Fixing"));
    aboutData.addCredit(i18n("Roland Schulz"), i18n("KatePart Integration"));
    aboutData.addCredit(i18n("Thorsten Lück"), i18n("Log Parsing"));
    aboutData.addCredit(i18n("Jan-Marek Glogowski"), i18n("Find-in-Files Dialog"));
    aboutData.addCredit(i18n("Jonathan Pechta"), i18n("Documentation"));
    aboutData.addCredit(i18n("Federico Zenith"), i18n("Documentation"));

    aboutData.setOrganizationDomain(QByteArray("kde.org"));
    aboutData.setDesktopFileName(QStringLiteral("org.kde.kile"));

    aboutData.setProductName(QByteArray("kile"));

    aboutData.setProgramLogo(QIcon(QStringLiteral(":/icons/sc-apps-kile.svg")));

    KAboutData::setApplicationData(aboutData);

    QApplication::setWindowIcon(QIcon(QStringLiteral(":/icons/sc-apps-kile.svg")));

    KCrash::initialize();

    QCommandLineParser parser;
    aboutData.setupCommandLine(&parser);

    parser.addOption(QCommandLineOption(QStringList() <<  QLatin1String("line"), i18n("Jump to line"), QLatin1String("line")));
    parser.addOption(QCommandLineOption(QStringList() <<  QLatin1String("new"), i18n("Start a new Kile mainwindow")));
//TODO KF5 VERIFY THAT '-' STILL WORKS
    parser.addPositionalArgument(QStringLiteral("urls"), i18n("Files to open / specify '-' to read from standard input"), QLatin1String("[urls...]"));

    parser.process(app);
    aboutData.processCommandLine(&parser);

    bool running = false;

    {
        const KDBusService dbusService(KDBusService::Multiple | KDBusService::NoExitOnFailure);

        QDBusConnectionInterface *interface = QDBusConnection::sessionBus().interface();

        if(interface) {
            running = interface->isServiceRegistered(QStringLiteral("org.kde.kile"));
        }
        else {
            KILE_WARNING_MAIN << "no DBUS interface found!";
        }
    }

    if(!running  || parser.isSet(QStringLiteral("new"))) {
        bool restore = (parser.positionalArguments().count() == 0);

        Kile *kile = new Kile(restore);

        // the constructor of the Kile class will return immediatey if Okular cannot be instantiated correctly
        if(!kile->viewManager()->viewerPart()) {
            delete kile;

            KILE_DEBUG_MAIN << "couldn't find a recent version of the Okular library";

            KMessageBox::error(nullptr, i18n("Kile cannot start as a recent version the Okular library could not be found.\n\n"
                                               "Please install the Okular library before running Kile."),
                                          i18n("Okular library not found"));
            return EXIT_FAILURE;
        }

        const QList<QString> argumentList = parser.positionalArguments();
        for(const QString& argument : argumentList) {
            if (argument == QStringLiteral("-")) {
                kile->openDocument(readDataFromStdin());
            }
            else {
                const QUrl url = QUrl::fromUserInput(argument, QDir::currentPath(), QUrl::AssumeLocalFile);

                if(isProject(url)) {
                    kile->openProject(url);
                }
                else {
                    kile->openDocument(url);
                }
            }
        }

        if(parser.isSet(QStringLiteral("line"))) {
            QString line = parser.value(QStringLiteral("line"));
            kile->setLine(line);
        }

        return app.exec();
    }
    else {
        auto interface = std::make_unique<QDBusInterface>(QStringLiteral("org.kde.kile"), QStringLiteral("/main"), QStringLiteral("org.kde.kile.main"));

        const QList<QString> arguments = parser.positionalArguments();
        for (const QString &argument : arguments) {
            if(argument == QLatin1Char('-')) {
                interface->call(QStringLiteral("openDocument"), readDataFromStdin());
            }
            else {
                const QUrl url = QUrl::fromUserInput(argument, QDir::currentPath(), QUrl::AssumeLocalFile);

                if(isProject(url)) {
                    interface->call(QStringLiteral("openProject"), url.url());
                }
                else {
                    interface->call(QStringLiteral("openDocument"), url.url());
                }
            }
        }

        if(parser.isSet(QStringLiteral("line"))) {
            QString line = parser.value(QStringLiteral("line"));
            interface->call(QStringLiteral("setLine"), line);
        }

        interface->call(QStringLiteral("setActive"));
    }

    return EXIT_SUCCESS;
}
