#ifndef __GLOBAL_H
#define __GLOBAL_H

#include <qobject.h>
#include <qfile.h>
#include <qcustomplot.h>

#include "protocol.h"
#include "analysisoperationrecorder.h"

namespace Global {
    const QString ExperimentDirPath = QDir::currentPath() + "/../experiment_data";

    const QString SampleDataFloder    = ExperimentDirPath + "/sample_data";
    const QString BaseLineFolder      = ExperimentDirPath + "/base_line";
    const QString AnalysisStateFolder = ExperimentDirPath + "/analysis_state";

    const QString CurveOfTimeTypeObjectName("curve_time");

    const int PhaseIndexDefault = -1;

    // json string.
    const QString AtomsphereData("atomsphereData");
    const QString SampleData("sampleData");

    const QString Atmosphere("atmosphere");
    const QString HeatingRate("heatingRate");

    const QString ElementName("elementName");
    const QString SampleName("sampleName");
    const QString TemperatureStr("temperature");
    const QString RateStr("rate");

    // 热焓修正系数
    const double DefaultParamter    = 8.177;
    const double OnsetAndEndSetRate = 0.01;

    // curve object name
    const QString ObjectNameExperiemnt("experiment");
    const QString ObjectNameSmooth("smooth");
    const QString Separator("___");
    //
    enum LanguageType {
        Chinese,
        English
    };

    enum AxisMode {
        SingleY,
        DoubleY
    };

    const QString EnglishStr("English");
    const QString ChineseStr("中文");

    enum Mode {
        None,
        Analysis,
        ConnectedToDev,
        DeliveredData,
        Experiment
    };

    enum DeviceConnectionStatus {
        Disconnected,
        Connected
    };

    struct ExperimentData {
        float runTime;
        float constantTempTime;
        float sampleTemp;
        float dsc;
        int   phaseIndex;

        ExperimentData()
            : runTime(0.0), constantTempTime(0.0), sampleTemp(0.0), dsc(0.0), phaseIndex(PhaseIndexDefault) {}
    };

    enum TestType {
        OIT,
        NoneOIT
    };

    struct ExperimentInfo {
        // experiment info
        QString sampleName;
        QString sampleWeight;
        QString date;
        QString experimentor;
        // phase info
        TestType testType;
        GasType  initialAtmosPhere;
        int      phaseSize;

        QVector<Phase> phaseVtr;

        ExperimentInfo()
            : sampleName("new"), sampleWeight("0"), date("20250101"), experimentor("experimentor") {}
    };

    struct PhaseTotalInfo {
        int                     phaseIndex;    // from 1 to 6.
        Phase                   phase;
        QCPCurve               *curve;
        QVector<ExperimentData> dataVtr;
        QVector<ExperimentData> smoothDataVtr;
    };

    struct CurveFileData {
        QString                                               filePath;
        Global::ExperimentInfo                                ei;
        QVector<Global::PhaseTotalInfo>                       phaseTotalVtr;
        QVector<AnalysisOperationRecorder::AnalysisOperation> analysisOperationVtr;
    };

    struct CurveExperimentData {
        int                             phaseIndex;    // from 1 to 6.
        QCPCurve                       *curve;
        QString                         fileName;    // discard
        QVector<Global::ExperimentData> dataVtr;
        QVector<ExperimentData>         smoothDataVtr;

        CurveExperimentData()
            : phaseIndex(PhaseIndexDefault), curve(nullptr) {}
    };

    // Soft mode.
    extern Mode _mode;
    // Xlsx file data.
    extern QVector<CurveFileData> _curveFileDataVtr;
    // Experiment setting data.
    extern int                          _currentPhase;
    extern ExperimentInfo               _experimentInfo;
    extern QVector<CurveExperimentData> _curveExperimentDataVtr;
    extern CurveExperimentData         *_currentCurveExperimentDataPtr;
    // extern bool _smoothnessFlag;

#if 0
// Smoothness data
extern QVector<CurveExperimentData> _curveSmoothnessDataVtr;
extern QString _smoothnessFileName;
#endif

    // Call clear function at the right time.
    void clearExperimentData();

    // Instrument coefficient.
    extern bool _enthalpyCoefficientEnableFlag;
    /// abc
    extern QVector<double> _enthalpyCoefficientVtr;
    // peak comprehensive ananlysis
    extern bool _displayTimeValue;
    //
    extern LanguageType _languageType;

    extern AxisMode _axisMode;

    extern bool _experimentOITFlag;

    // OIT auto mode.
    const double OITAutoAnalysisDefaultCoefficient = 10.0;
    const double OITAutoAnalysisDefaultThreshold   = 2.0;

    extern bool   _OITAutoAnalysisModeFlag;
    extern double _OITAutoAnalysisCoefficient;
    extern double _OITAutoAnalysisThreshold;

    // common func
    QString converDoubleToStr(const double);
    double  converStrToDouble(const QString);
    void    quadraticLeastSquaresFit(double x[], double y[], int n, double coeff[]);
    double  findNegativeStartPoint(double m, double b, double start, double end);
    bool    isZero(double value, double epsilon = 1e-9);
    bool    isEqual(const double a, const double b);
    QString getFileName(const QString filePath);

    // 实验文件
    extern QStringList _fileList;
    void               updateFileList();
    bool               isFileExist(const QString &fileName);

};    // namespace Global

#endif    // GLOBAL_H
