// bytran -|- spectral calculations for portable devices using the HITRAN database
//
// Developed by Dzianis Pliutau (Denis Plutov) and Kostya Roslyakov
// www.bytran.org | contact@bytran.org
// Copyright (c) 2016 Dzianis Pliutau
// Distributed under the MIT license
//
// Version 1.0 Release information
// Release history (Android), Version 5.6.1-1 of Qt was used to compile the software under Android to keep older interface:
//      Version 1.0 Alpha for Android uploaded to GooglePlay on May 16, 2016.
//      Version 1.0 Beta for Android uploaded to GooglePlay on May 31, 2016, submitted to production (publicly available) on Google Play on June 4, 2016
//      Version 1.0 for Android released on Google Play on July 4, 2016
// Release history (iOS):
//      Didn't record when the application was first tested on an iOS device (Alpha testing)
//      Version 1.0 Beta for iOS first submitted to AppStore on August 3, 2016 as a Beta TestFlight
//      Version 1.0 Beta for iOS published to the App Store on September 30, 2016
// Release history (WinRT, Windows Phone):
//      Version 1.0 Alpha for Windows Phone (WinRT) first tested on a Windows phone device on August 11, 2016.
//      Version 1.0 Beta for Windows Phone (WinRT) first uploaded to the Windows App Store on September 14, 2016
// Release history (Windows):
//      Version 1.0 Alpha for Windows first made available as a ZIP file on May 26, 2016
//      Version 1.0 Beta made available as a ZIP file on June 13, 2016
//      Version 1.0 made available as a ZIP file on August 1, 2016
// Release history (OS X):
//      Version 1.0 Alpha for OS X released as a DMG archive on June 10, 2016
//      Version 1.0 Beta for OS X released as a DMG archive on June 13, 2016
//      Version 1.0 for OS X released as a DMG archive on September 23, 2016
// Release history (Linux):
//      Version 1.0 Alpha for Linux first made available as a TAR archive on June 10, 2016
//      Version 1.0 Beta for Linux released as a TAR archive on June 13, 2016
//      Version 1.0 released as a TAR archive on September 8, 2016
// Source code release history:
//      Version 1.0 Beta placed online on September 16, 2016
//
// Version 1.1 Release history information
//      for Android (Qt 5.9.1 used), iOS (Qt 5.7.1 used), and Windows Phone (Qt 5.7.1 used) were submitted to the app stores on July 10, 2017 for all 3 platforms
//      for Windows (Qt 5.9.1 used) and Mac (Qt 5.7.1 used) were placed online as ZIP and DMG archives on July 11, 2017
//      for Ubuntu Linux (Qt 5.9.0 Beta 3 used) was placed online as an TAR archive on July 13, 2017
//      for Raspbian Jessie Linux (Qt 5.9.0 Beta 3 used) was placed online as TAR archive on July 15, 2017
// Source code release history:
//      Version 1.1 placed online on July 15, 2017
//
// The bytran logo is distributed under the Creative Commons 3.0 Attribution License: https://creativecommons.org/licenses/by/3.0/us/
//
//
// The MIT License (MIT)
// Copyright (c) 2016 Dzianis Pliutau
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


// #include <QGuiApplication>  // http://www.qtcentre.org/threads/60203-QApplication-QGuiApplication-and-QCoreApplication
#include <QApplication>        // Using QWidgets because the plot is currently plotted using QWidget, maybe could replace this in the future
#include <QQmlApplicationEngine>
#include <QQmlApplicationEngine>
#include <QQuickView>
#include <QQmlContext>
#include <QSplashScreen>
#include <QTimer>
#include "mollistviewmodel.h"
#include "mollistviewreducedmodel.h"
#include "pathlengthdataobject.h"
#include "wavelengthdataobject.h"
#include "totalpressdataobject.h"
#include "atmospheredataobject.h"
#include "temperaturedataobject.h"
#include "wavelengthdataobject.h"
#include "lineoptionsdataobject.h"
#include "notifierdataobject.h"
#include "instrumentalfunctiondataobj.h"
#include "spectraresultsdataobject.h"
#include "hitrandownloadoptionsdataobject.h"
#include "shareresultsdataobject.h"
#include "aboutdataobject.h"
#include "sensorsdataobject.h"
#include "spectrum.h"
#include "plot.h"
#include "colorplot.h"
#include "bytrancore.h"
#include "yaxis.h"
#include "yaxisdataobject.h"

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QApplication app(argc, argv);  // A the application creation time this was a QGuiApplication

    // Registering type for plotting the results of the calculations
    qmlRegisterType<Plot>("Plot", 1, 0, "Plot");
    qmlRegisterType<ColorPlot>("ColorPlot", 1, 0, "ColorPlot");
    qRegisterMetaType<Spectrum>("Spectrum");

    // Setting the application name
    app.setApplicationName("bytran");

    // Initializing the Core calculation class
    BytranCore *core;
    core = new BytranCore();

    // Need to adjust font for the iOS (Maybe remove this approach completely and adjust the interface on the main page the same way as in the modal dialogs)
    #if defined(Q_OS_IOS)

        QFont font;
        font = app.font();
        int fontSize = font.pointSize();

        // This adjustment is for the iOS case only (to make the components fit within the device screen)
        if (core->iPhone())
        {
            // iPhone is a bit smaller in size than iPad
            fontSize = fontSize - 4;
        }
        else
        {
            // iPad text is a little larger in size
            fontSize = fontSize - 1;
        }

        // Font adjustment for the iPhone and iPad
        font.setPointSize(fontSize);
        app.setFont(font);

    #endif 

    // This initialization may need to be done elsewhere
    MolListViewModel *moleculesModel;
    moleculesModel = new MolListViewModel(0, core);
    MolListViewReducedModel *moleculesReducedModel;
    moleculesReducedModel = new MolListViewReducedModel(0, core);
    PathlengthDataObject *pathlengthDataObj;
    pathlengthDataObj = new PathlengthDataObject(0, core);
    WavelengthDataObject *wlDataObj;
    wlDataObj = new WavelengthDataObject(0, core);
    TotalPressDataObject *totalPressObject;
    totalPressObject = new TotalPressDataObject(0, core);
    AtmosphereListViewModel *atmDataObject;
    atmDataObject = new AtmosphereListViewModel(0, core);
    TemperatureDataObject *tempDataObject;
    tempDataObject = new TemperatureDataObject(0, core);
    WavelengthDataObject *wlDataObject;
    wlDataObject = new WavelengthDataObject(0, core);
    LineOptionsDataObject *lineOptDataObject;
    lineOptDataObject = new LineOptionsDataObject(0, core);
    NotifierDataObject *notifyDataObject;
    notifyDataObject = new NotifierDataObject(0, core);
    YAxisDataObject *yaxisDataObject;
    yaxisDataObject = new YAxisDataObject(0, core);
    InstrumentalFunctionDataObj *instrFunctDataObject;
    instrFunctDataObject = new InstrumentalFunctionDataObj(0, core);
    SpectraResultsDataObject *specResultsDataObject;
    specResultsDataObject = new SpectraResultsDataObject(0, core);
    HitranDownloadOptionsDataObject *hitranDownloadOptionsDataObj;
    hitranDownloadOptionsDataObj = new HitranDownloadOptionsDataObject(0, core);
    ShareResultsDataObject *shareResultsDataObj;
    shareResultsDataObj = new ShareResultsDataObject(0, core);
    AboutDataObject *aboutDataObj;
    aboutDataObj = new AboutDataObject(0, core);
    SensorsDataObject *sensorsDataObj;
    sensorsDataObj = new SensorsDataObject(0, core);

    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty("coreObj", core);  // Core calculation object used to invoke calcualtions etc.
    engine.rootContext()->setContextProperty("molListViewModel", moleculesModel);  // This is done to register the model component for the molecules QML "window"
    engine.rootContext()->setContextProperty("molListViewReducedModel", moleculesReducedModel);  // This is done to register the model component for the molecules QML "window"
    engine.rootContext()->setContextProperty("pathlengthObj", pathlengthDataObj);  // This is done to register the pathlength data object with the corresponding QML interface component
    engine.rootContext()->setContextProperty("wlObj", wlDataObj);                  // This is for the wavelength window to set up the start and end wavelengths for the calculations to be performed properly
    engine.rootContext()->setContextProperty("totalPressObj", totalPressObject);   // Linking for the total pressure interface components to be used for total pressure specification
    engine.rootContext()->setContextProperty("atmDataObj", atmDataObject);         // Linking the atmospehric model QML components with the C++ data objects
    engine.rootContext()->setContextProperty("tempDataObj", tempDataObject);       // Linking the temperature QML component with the C++ data object
    engine.rootContext()->setContextProperty("wlDataObj", wlDataObject);           // Linking the wavelengths QML interface component with the C++ code
    engine.rootContext()->setContextProperty("lineOptDataObj", lineOptDataObject); // Linking line options QML interface component with the C++ code
    engine.rootContext()->setContextProperty("notifyObj", notifyDataObject);       // Object to display notification messages
    engine.rootContext()->setContextProperty("yAxisObj", yaxisDataObject);         // Object to change the vertical scale boundaries (minimum to maximum)
    engine.rootContext()->setContextProperty("instrFunctDataObj", instrFunctDataObject);    // Object to change the selected instrument function and related paramters
    engine.rootContext()->setContextProperty("specResultsDataObj", specResultsDataObject);  // Object to enable internaction between the core class and the spectrum plot
    engine.rootContext()->setContextProperty("hitranDownloadOptionsDataObj", hitranDownloadOptionsDataObj);  // Object to change the way the HITRAN database is used (segmented download, complete download or online access every time)
    engine.rootContext()->setContextProperty("shareResultsDataObj", shareResultsDataObj);   // Data object linking the QML component for saving the results with the core components performing calculations and data saving
    engine.rootContext()->setContextProperty("aboutDataObj", aboutDataObj);        // Data object to open a paypal donate window
    engine.rootContext()->setContextProperty("sensorsDataObj", sensorsDataObj);    // Data object to interact with the sensors C++ class

    engine.load(QUrl(QLatin1String("qrc:/main.qml")));

    return app.exec();
}
