/*****************************************************************************
 *
 * Testmanager - Graphical Automation and Visualisation Tool
 *
 * Copyright (C) 2018  Florian Pose <fp@igh.de>
 *
 * This file is part of Testmanager.
 *
 * Testmanager 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.
 *
 * Testmanager 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 Testmanager. If not, see <http://www.gnu.org/licenses/>.
 *
 ****************************************************************************/

#ifdef _WIN32
#include <Python.h>
#endif
#include "MainWindow.h"
#include "SlotModel.h"
#include "DataNode.h"

#ifndef _WIN32
#include "SignalReceiver.h"
#endif

#include <QtPdWidgets2/Widget.h>
#include <QtPdWidgets2/Translator.h>

#include <QtPdCom1/Translator.h>
#include <QtPdCom1/LoginManager.h>

#include <QApplication>
#include <QTranslator>
#include <QLibraryInfo>

#include <iostream>
#include <sstream>
using namespace std;

#include <getopt.h>
#include <libgen.h> // basename()

#ifndef _WIN32
#include <signal.h> // SIGINT/SIGTERM
#endif

/****************************************************************************/

string binaryBaseName;
int get_options(int, char **);

// command-line argument variables
bool newView = false;
bool autoConnect = false;
QString fileName;

/****************************************************************************/

string usage()
{
    stringstream str;

    str << "Usage: " << binaryBaseName << " [OPTIONS] [ <FILENAME> ]" << endl
        << endl
        << "Global options:" << endl
        << "  --new           -n         Start with empty view." << endl
        << "  --help          -h         Show this help." << endl
        << "  --connect       -c         Connect immediately and try" << endl
        << "                             to stay connected." << endl
        << endl
        << "FILENAME is a path to a stored layout (*.tml), that" << endl
        << "  will be loaded on start-up." << endl;

    return str.str();
}

/****************************************************************************/

int main(int argc, char *argv[])
{
    binaryBaseName = basename(argv[0]);

    int ret = get_options(argc, argv);
    if (ret) {
        return ret;
    }

    //------------------------------------------------------------------------
    // static initialisations

    QCoreApplication::setOrganizationName("EtherLab");
    QCoreApplication::setOrganizationDomain("etherlab.org");
    QCoreApplication::setApplicationName("Testmanager NG");

    Pd::Widget::setRedrawInterval(40);

    //------------------------------------------------------------------------
    // init application

    QApplication app(argc, argv);

    SlotModel::initCustomColors();
    DataNode::loadIcons();

    //------------------------------------------------------------------------
    // initialize SASL

    //------------------------------------------------------------------------
    // win32: set python home relative to the location of testmanager.exe
    QtPdCom::LoginManager::InitLibrary();
#ifdef _WIN32
    static const std::wstring pythonHome =
            (QCoreApplication::applicationDirPath() + "/../").toStdWString();
    Py_SetPythonHome(pythonHome.data());
#endif

    //------------------------------------------------------------------------
    // locale

    // retrieve system locale
    QLocale::setDefault(QLocale(QLocale::system().name()));

    // load Qt's own translations
    QTranslator qtTranslator;
    qtTranslator.load("qt_" + QLocale::system().name(),
            QLibraryInfo::location(QLibraryInfo::TranslationsPath));
    app.installTranslator(&qtTranslator);

    // PdWidgets translations
    QTranslator pdTranslator;
    Pd::loadTranslation(pdTranslator);
    app.installTranslator(&pdTranslator);

    QTranslator qtPdComTranslator;
    QtPdCom::loadTranslation(qtPdComTranslator);
    app.installTranslator(&qtPdComTranslator);

    // load own translations
    QTranslator translator;
    translator.load(":/testmanager_" + QLocale::system().name());
    app.installTranslator(&translator);

    //------------------------------------------------------------------------
    // init main window

    MainWindow wnd(fileName, newView, autoConnect);

#ifndef _WIN32
    SignalReceiver sigRec;
    QObject::connect(&sigRec, SIGNAL(signalRaised(int)),
            &wnd, SLOT(signalRaised(int)));
    sigRec.install(SIGINT);
    sigRec.install(SIGTERM);
#endif

    QApplication::connect(wnd.actionAboutQt, SIGNAL(triggered()),
                          &app, SLOT(aboutQt()));

    wnd.show();

    return app.exec();
}

/****************************************************************************/

int get_options(int argc, char **argv)
{
    static struct option longOptions[] = {
        // name,      has_arg,           flag, val
        {"connect",   no_argument,       NULL, 'c'},
        {"help",      no_argument,       NULL, 'h'},
        {"new",       no_argument,       NULL, 'n'},
        {NULL,        0,                 0,    0  }
    };

    int c;
    do {
        c = getopt_long(argc, argv, "chn", longOptions, NULL);

        switch (c) {
            case 'c':
                autoConnect = true;
                break;

            case 'h':
                cout << usage();
                return 2;

            case 'n':
                newView = true;
                break;

            case '?':
                cerr << endl << usage();
                return 1;

            default:
                break;
        }
    }
    while (c != -1);

    unsigned int argCount = argc - optind;
    if (argCount > 1) {
        cerr << binaryBaseName
            << " takes either zero arguments or one argument."
            << endl << endl;
        cerr << usage();
        return 1;
    }

    if (argCount == 1) {
        fileName = argv[optind];
    }

    return 0;
}

/****************************************************************************/
