// 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
//
// 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.



// This class is used to download data from the HITRAN online interface. The data includes the
// molparam.txt file, the files with the total internal partition sums and the HITRAN database file.
// The module also includes a subclass to access HITRAN database in a standard format of a disk.
#ifndef HITRANONLINEDOWNLOADER_H
#define HITRANONLINEDOWNLOADER_H

#include <QString>
#include <QObject>
#include "serverlogin.h"
#include "hitranrequestdata.h"
#include "normalizeddownloadregionsfinder.h"
#include "hitraninputoutput.h"
#include "filedownloader.h"
#include "tipsfilesdownloader.h"
#include "hitranonerec.h"

class HitranOnlineDownloader : public QObject
{
    Q_OBJECT

signals:

    // Signal used to send notifications to the user of what is going on in the program
    void notify(QString message, double value, bool visible, bool cancelButtonVisible);

    // Signal is emitted after the download of the HITRAN database
    void hitranDownloadComplete();

    // Signal is emited when the data becomes available (either read in from a file or downloaded)
    void dataAvailable();

    // Emitted when no more data is available
    void noMoreDataAvailable();

    // Signal is emited when molparam.txt download is complete
    void molparamTxtDownloadComplete();

    // Signal is emited when the TIPS data download is complete
    void tipsDownloadComplete();

    // Signal is emited if the HITRAN database download is unsuccessful
    void hitranDownloadUnsuccessful();

    // Singnal is emited to open the ok notification dialog
    void openOkDialog(QString text);

public:

    HitranOnlineDownloader(QObject *parent);

    // Method to get the number of records to be read in from the HITRAN file
    quint64 getTotalNumRecsToProcess();

    // Method is to carry out complete HITRAN online database download (segmented files which will be stored separately)
    void downloadCompleteSegmentedHitran();

    // Method to download the molparam.txt file
    void downloadMolparamTxt();
    // Method to download files with the total internal partition sums
    void downloadTipsFiles();

    // Method to initiate the HITRAN download quiery
    QString formQuery(double fromWn, double toWn);

    // Method to download hitran
    void getHitranData();
    void getHitranData(bool newUseAuthen);

    // Methods to get and set the host name to download the HITRAN database
    QString getHitranHostName();
    void setHitranHostName(QString newHostName);

    // Cumulative HITRAN database download path (for the complete HITRAN database to be downloaded)
    QString getCumulativeHitranDownloadPath();
    void setCumulativeHitranDownloadPath(QString newCumulativeHitranDownloadPath);

    // Methods to get and set the paths to the folders where HITRAN, molparam.txt, and the TIPS files are stored
    QString getMolparamFolder();
    void setMolparamFolder(QString newMolparamFolder);

    // Getting and setting the minimum and maximum download wavenumbers
    double getStartWn();
    void setStartWn(double newStartWn);
    double getEndWn();
    void setEndWn(double newEndWn);

    // Getting and setting the HITRAN complete file path (where the complete HITRAN database file is to be stored)
    QString getCumulativeHitranPath();
    void setCumulativeHitranPath(QString newCumulativeHitranPath);

    // Name of the file to save the downloaded data to (cumulative HITRAN file name), this file is completed by carrying out downloads in small portions
    QString getSegmentedHitranPath();
    void setSegmentedHitranPath(QString newSegmentedHitranPath);

    // Name of the file to save the downloaded complete HITRAN file to
    QString getCumulativeHitranFile();
    void setCumulativeHitranFile(QString newCumulativeHitranFile);

    // Name of the file containing the list of continuous spectral regions which the HITRAN data has already been downloaded for
    QString getDownloadHistoryFile();
    void setDownloadHistoryFile(QString newDownloadHistoryFile);

    // Method to set the HITRAN hostname, email and password
    QString getHitranLoginHost();
    void setHitranLoginHost(QString hostName);

    // Getting and setting the HITRAN email
    QString getHitranEmail();
    void setHitranEmail(QString newEmail);

    // Getting and setting the HITRAN password
    QString getHitranPassword();
    void setHitranPassword(QString newPassword);

    // Setting the variable indicating if authentication is to be used in remote data access
    bool getUserAuthen();
    void setUserAuthen(bool newUserAuthen);

    // Paths to the online download folders with the molparam and the TIPS files
    QString getMolparamDownloadPath();
    void setMolparamDownloadPath(QString newMolparamDownloadPath);

    // Number of the start record in the cumulative HITRAN data file
    int getStartWnByte();
    void setStartWnByte(int newStartWnByte);
    // Number of the end record in the cumulative HITRAN data file
    int getEndWnByte();
    void setEndWnByte(int newEndWnByte);
    // Number of the starting subrange record
    int getStartSubrangeWnByte();
    void setStartSubrangeWnByte(int newStartSubrangeWnByte);
    // Number of the ending subrange record
    int getEndSubrangeWnByte();
    void setEndSubrangeWnByte(int newEndSubrangeWnByte);
    // Number of records in the subrange to read in one reading
    quint32 getSubrangeRecordsStep();
    void setSubrangeRecordsStep(quint32 newSubrangeRecordsStep);

    // Method to get the TIPS object
    TipsFilesDownloader *getTipsDownloader();

    // Method to get the file downloader
    FileDownloader *getFileDownloader();

    // Method to get logon to a remote host
    ServerLogin *getLoginObj();

    // Method to get data to be used in calculations
    QVector<HitranOneRec> *getHitranRecs();

    // Getting and setting the variable indicating the type of HITRAN database usage to implement
    int getHitranFileUsage();
    void setHitranFileUsage(int newHitranFileUsage);

    // Method to set a reference to the molecules array
    void setMolArray(QVector<HitranOneMol> *newMol);

    // Method to determine if the complete HITRAN database file is present on the user's device
    int getCompleteHitranDbFileExists();

    // Method to determine the HITRAN database record boundaries for the entire spectral region based on the start and end wavenumbers
    void getHitranRecordBoundaries();

    // Method to get the next records subrange
    void getNextSubrange();

    // Method is used to set a variable used to cancel the calculation
    void setCancelCalculation(bool newCancelCalculation);

private slots:

    // Slot to process the server downloaded data
    void processServerReturnedData(QByteArray *hitranData, bool success);

    // Slot indicating that authentication has been completed
    void authenticationComplete();

    // Slot is called after the molparam file has been downloaded
    void molparamDownloaded(QByteArray *molparamData, bool success);

    // Slot is called once the TIPS files have finished downloading
    void tipsFilesDownloaded(bool success);

    // Method to send an initial download request
    void sendInitialDownloadRequest();

private:

    // Private method to get HITRAN data over a specified spectral region
    void getHitranData(bool newUseAuthen, double startWn, double endWn);

    // Method to set the database folders and files
    void setFolders();

    // Method called to request data from a remote server
    void sendDataRequest(double fromWn, double toWn);
    void sendDownloadEveryTimeDataRequest();

    // Method to create actions (connections to carry out further operations)
    void createActions();

    // Host name string
    QString hostName;  // http://www.hitran.org/lbl/

    // Sub-query string (line-by-line)
    QString lblSubQueryStrWithAuthen;     // String to contain additional characters for line-by-line query with authentication
    QString lblSubQueryStrWithoutAuthen;  // String to contain additional characters for line-by-line query without authentication

    // Folder path to save the downloaded complete HITRAN database file to
    QString cumulativeHitranPath;

    // Name of the file to save the downloaded data to (cumulative HITRAN file name)
    QString cumulativeHitranFile;

    // Name of the file containing the list of continuous spectral regions which the HITRAN data has already been downloaded for
    QString downloadHistoryFile;

    // Paths to the folders to save the downloaded data to
    QString molparamFolder;  // Path to the folder with the molparam.txt file
    QString tipsFolder;      // Path to the folder with the TIPS data

    // Paths to the online download folders with the molparam and the TIPS files
    QString molparamDownloadPath;
    QString tipsDownloadPath;

    // Minimum and maximum spectral ranges specified by the user
    double startWn;  // Minimum download wavenumber
    double endWn;    // Maximum download wavenumber
    int startWnFileIndex; // Starting file index for the segmented HITRAN access
    int endWnFileIndex;   // Ending file index for the segmented HITRAN access
    int startSubrangeWnFileIndex; // Starting subrange file index for the segmented HITRAN access
    int endSubrangeWnFileIndex;   // Ending subrange file index for the segmented HITRAN access
    quint64 startWnByte;  // Number of the start record in the cumulative HITRAN data file
    quint64 endWnByte;    // Number of the end record in the cumulative HITRAN data file
    quint64 startSubrangeWnByte;  // Number of the starting subrange record byte
    quint64 endSubrangeWnByte;    // Number of the ending subrange record byte
    quint32 subrangeRecordsStep;  // Number of records (not bytes) in the subrange to read in one reading

    // Spectral ranges which need to be downloaded from the HITRAN server
    QVector <double> minWnDownloadRegions;  // Array to contain the starting wavenumbers of the required download regions
    QVector <double> maxWnDownloadRegions;  // Array to contain the ending wavenumbers of the required download regions

    // Data downloaded for each spectral data region
    QStringList downloadedData;

    // Variable indicates if authentication needs to be used when accessing the remote server
    bool userAuthen;

    // Object to carry out remote host authenification
    ServerLogin *login;

    // Object to request data from HITRAN
    HitranRequestData *requestData;

    // Object to determine the download regions for data
    NormalizedDownloadRegionsFinder *downloadRegionsFinder;

    // Object for saving of data to the HITRAN file
    HitranInputOutput *hitranio;

    // Variable indicating the number of the HITRAN downloaded regions (use used to only update the download history file one time)
    int numHitranRegionsDownloaded;

    // File downloader object to download the TIPS files and the file with the molecular information
    FileDownloader *fileDownloader;

    // Object to download TIPS files
    TipsFilesDownloader *tipsDownloader;

    // TIPS maximum index
    int tipsMaxIndex;

    // Variable indicating if the HITRAN database should be accessed of the disk or downloaded (thd download option is the default)
    int hitranFileUsage;  // 0 - download and save HITRAN file in segments as the need arises and store them locally for later reuse offline (previously unaccessed segments would have to be downloaded);
                          // 1 - use cumulative HITRAN file (download complete HITRAN file once only and later use it offline);
                          // 2 - dowload HITRAN segments from hitran.org every time, no storing of data on the mobile device (not recommended)

    QString cumulativeHitranDownloadPath;  // Path to download the cumulative HITRAN database (HTTP not requiring any FTP access.)

    // Array with molecules
    QVector<HitranOneMol> *mol;

    // Variable set to cancel the calculation
    bool cancelCalculation;

};

#endif // HITRANONLINEDOWNLOADER_H
