#ifndef CANDLE_CHART_MODEL_H
#define CANDLE_CHART_MODEL_H

#include "../../TradeCore/chart_candle.hh"
#include <QDateTime>
#include <QMap>
#include <QObject>
#include <memory>
#include <array>

///< Type for CandleChartModel iterator
typedef QMap<QDateTime, ChartCandle>::iterator CandleChartIterator;

///< Type for CandleChartModel const iterator
typedef QMap<QDateTime, ChartCandle>::const_iterator CandleChartConstIterator;

///< Time period of candle chart (candle width)
enum class ChartScale
{
    M1 = 0, ///< One minute
    M5 = 1, ///< Five minutes
    M15 = 2, ///< Fifteen minutes
    M30 = 3, ///< Thirty minutes
    H1 = 4, ///< One hour
    H4 = 5, ///< Four hours
    D1 = 6, ///< One day
    W1 = 7, ///< One week
    MN = 8, ///< One month
    NONE = 9 ///< Undefined
};

/**
 * @brief List of chart scales
 */
constexpr std::array<ChartScale, 10> chartScales = {
    ChartScale::M1, ChartScale::M5, ChartScale::M15, ChartScale::M30,
    ChartScale::H1, ChartScale::H4, ChartScale::D1, ChartScale::W1,
    ChartScale::MN, ChartScale::NONE};

/**
 * @brief Convert chart scale enumeration value to string
 */
QString chartScaleToString(ChartScale scale);

/**
 * @brief Convert string to chart scale enumeration value
 */
ChartScale chartScaleFromString(const QString& str);

///< List of currency pairs and other merchantable stuff
enum class CurrencyPair
{
    NONE = 0, ///< Undefined
    EURUSD = 1, ///< Euro - US Dollar
    USDJPY = 2, ///< US Dollar - Japanese Yen
    GPBUSD = 3, ///< British Pound - US Dollar
    USDCHF = 4, ///< US Dollar - Swiss Franc
    USDCAD = 5, ///< US Dollar - Canadian Dollar
    EURJPY = 6, ///< Euro - Japanese Yen
    EURGPB = 7, ///< Euro - British Pound
    EURCAD = 8, ///< Euro - Canadian Dollar
    GPBJPY = 9, ///< British Pound - Japanese Yen
    GPBCHF = 10, ///< British pound - Swiss Franc
    GPBNZD = 11, ///< British pound - New Zealand Dollar
    CHFJPY = 12, ///< Swiss Franc - Japanese Yen
    AUDJPY = 13
};

/**
 * @brief List of currency pairs
 */
constexpr std::array<CurrencyPair, 14> currencyPairs = {
    CurrencyPair::NONE, CurrencyPair::EURUSD, CurrencyPair::USDJPY,
    CurrencyPair::GPBUSD, CurrencyPair::USDCHF, CurrencyPair::USDCAD,
    CurrencyPair::EURJPY, CurrencyPair::EURGPB, CurrencyPair::EURCAD,
    CurrencyPair::GPBJPY, CurrencyPair::GPBCHF, CurrencyPair::GPBNZD,
    CurrencyPair::CHFJPY, CurrencyPair::AUDJPY};

/**
 * @brief Convert currency pair enumeration value to string
 */
QString currencyPairToString(CurrencyPair pair);

/**
 * @brief Convert string to currency pair enumeration value
 */
CurrencyPair currencyPairFromString(const QString& str);

/**
 * @brief Candle chart data model
 * Data are stored in map with date-time as keys
 */
class CandleChartModel
{
public:
    CandleChartModel();
    CandleChartModel(const QList<ChartCandle>& data, ChartScale scale = ChartScale::NONE,
                     CurrencyPair pair = CurrencyPair::NONE);
    CandleChartModel(ChartScale scale, CurrencyPair pair);
    CandleChartModel(QString& str);
    CandleChartIterator begin();
    CandleChartIterator end();
    CandleChartConstIterator cbegin() const;
    CandleChartConstIterator cend() const;
    ChartCandle& first();
    ChartCandle& last();
    ChartCandle& operator[](const QDateTime& dateTime);
    ChartCandle& operator[](int index);
    int count() const;
    bool isEmpty() const;
    void insert(const ChartCandle& candle);
    void remove(const QDateTime& dateTime);
    void clear();
    ChartScale chartScale() const;
    CurrencyPair currencyPair() const;
    QString toString() const;
    double max() const;
    double min() const;

private:
    CandleChartModel(const CandleChartModel&) = delete;
    CandleChartModel& operator=(const CandleChartModel&) = delete;

private:
    QMap<QDateTime, ChartCandle> data_;
    ChartScale scale_;
    CurrencyPair pair_;
};

///< Candle chart model pointer
typedef std::shared_ptr<CandleChartModel> CandleChartModelPtr;

/**
 * @brief Load candle chart model data from file
 */
CandleChartModelPtr loadChartData(const QString& filename);

/**
 * @brief Model to vector of candle average values
 */
QString toLineString(const CandleChartModel& model);

/**
 * @brief Save candle chart model data to file
 */
void saveChartData(const QString& filename, const CandleChartModel& chartModel);

/**
 * @brief Save candle chart line to file
 */
void saveChartLine(const QString& filename, const CandleChartModel& chartModel);

#endif // CANDLE_CHART_MODEL_H
