#ifndef CALCULATE_PARKING_TICKETS_TARIFF_H_INCLUDED
#define CALCULATE_PARKING_TICKETS_TARIFF_H_INCLUDED

#include "calculate_parking_tickets_global.h"
#include "calculate_parking_tickets_tariff_step.h"
#include <QDateTime>
#include <QVector>
#include <QSet>
#include <QPair>
#include <QList>

#define FAHRZEUG_AUSWAHL_PKW            (uint64_t)(0x0000000000000001)
#define FAHRZEUG_AUSWAHL_BUS            (uint64_t)(0x0000000000000002)
#define FAHRZEUG_AUSWAHL_LKW            (uint64_t)(0x0000000000000004)
#define VERANSTALTUNG_AUSWAHL_SPORT     (uint64_t)(0x0000000000000008)
#define VERANSTALTUNG_AUSWAHL_KULTUR    (uint64_t)(0x0000000000000010)

struct parking_tariff_t {
    explicit parking_tariff_t()
        : day_tariff_start(0)
        , day_tariff_end(0)
        , night_tariff_start(0)
        , night_tariff_end(0) {
    }

    static parking_tariff_t *parseTariff(const char *confFile);

    /// \brief Express computational units in cent.
    ///
    /// The internal computations do not use the unit "cent" \n
    /// directly. Rather virtual integer value <b>unit_definition</b> is used, expressing \n
    /// how many cents correspond to <b>unit_definition</b> units.
    uint32_t unit_definition;

    /// \brief Scale units to cent.
    ///
    double unit_scale_factor;

    /// \brief VAT (Mehrwertsteuer) in percent.
    ///
    double vat;

    QSet<QDate> holidays;

    ///
    /// \brief m_tariffSteps
    ///
    TariffStep m_tariffSteps[3][7][MIN_PER_DAY];

    ///
    /// \brief day_tariff_start
    ///
    minute_t day_tariff_start;

    ///
    /// \brief day_tariff_end
    ///
    minute_t day_tariff_end;

    ///
    /// \brief night_tariff_start
    ///
    minute_t night_tariff_start;

    ///
    /// \brief night_tariff_end
    ///
    minute_t night_tariff_end;

    ///
    /// \brief waiting_period
    /// @note Also called "Karenzzeit". Allowed values: [0, 3]
    minute_t waiting_period;

    ///
    /// \brief free_of_charge
    ///
    minute_t free_of_charge_day_tariff;

    ///
    /// \brief free_of_charge_night_tariff
    ///
    minute_t free_of_charge_night_tariff;

    ///
    /// \brief max_parking_price_units
    ///
    uint32_t max_parking_price_units;

    ///
    /// \brief max_price_for_24_hours
    ///
    uint32_t max_price_for_24_hours;    // 24h limit (default -1)

    ///
    /// \brief tariff_version
    ///
    char tariff_version[64];

    ///
    /// \brief tariff_features
    ///
    uint64_t tariff_features;

    ///
    /// \brief _tariff_features
    ///
    uint64_t _tariff_features[64];

    ///
    /// \brief parking_time_min
    ///
    minute_t parking_time_min;

    ///
    /// \brief parking_time_max
    ///
    minute_t parking_time_max;

    ///
    /// \brief basic_tariff
    ///
    bool basic_tariff;

    ///
    /// \brief max_price_24h_after_arrival
    ///
    uint32_t max_price_24h_after_arrival;

    ///
    /// \brief max_price_at_midnight
    ///
    uint32_t max_price_at_midnight;

#if 0
    /// Minimal amount of money for buying a ticket.
    ///
    /// The minimal amount of money a user has to provide \n
    /// to get a valid (parking) ticket.
    uint32_t money_min;

    ///
    /// \brief Minimal parking time.
    ///
    /// Minimal parking time. The full parking time must be \n
    /// a multiple of @see parking_time_min.
    minute_t parking_time_min;

    ///
    /// \brief Maximal parking time. Must be a multiple of @see parking_time_min.
    ///
    minute_t parking_time_max;

    ///
    /// \brief integration_time_max
    /// Maximal possible integration time, i.e. the time after which all tickets
    /// will be closed.
    /// \note parking_time_max <= integration_time_max.
    minute_t integration_time_max;

    ///
    /// \brief tages_ticket_uebertrag
    ///
    bool tages_ticket_uebertrag;

    ///
    /// \brief free_of_charge_uebertrag
    /// Carry FOC (usually at midnight) or not.
    /// The default setting is true.
    bool free_of_charge_uebertrag;

    /// \brief Time for optionally changing tariff-table.
    ///
    /// Depending on the configuration, a table in the tariff can be swapped
    /// in, typically at midnight. But it is also possible that this event happens
    /// during the day.
    /// @note 0 &le; tariff_deadline $lt; 1440
    minute_t tages_ticket_offset;

    ///
    /// \brief vorkauf
    ///
    /// Maximal time in minutes before business hours where a presales
    /// ("vorkauf") operation is possible.
    minute_t vorkauf;

    /// \brief Memory consumption of calculate price algorithm
    uint32_t memory_consumption;

    ///
    /// Time-range which is free of charge.
    ///
    struct free_of_charge_range_t free_of_charge;

    ///
    /// \brief business_hours
    ///
    struct business_hours_range_t business_hours;


    /// Array of possible days: DEFAULT, SUN - SAT plus HOLIDAY.
    ///
    day_t *day[DAYS];

    /// Pointer to current day in tariff-table.
    ///
    day_t *current_day;

    /// Array of holiday dates. Format: YYYY:MM:DD
    ///
    holiday_date_t *holiday_date;

    ///
    /// \brief algorithm_features
    ///
    uint16_t algorithm_features;

    ///
    /// \brief tariff_features
    ///
    /// @todo: add comment
    uint64_t tariff_features;

    ///
    /// \brief _tariff_features
    ///
    /// @todo: add comment
    uint64_t _tariff_features[64];

    ///
    /// @brief closed_tickets_local_end_times
    ///
    /// @note The end times of all closed tickets: the possible values are
    ///       0 <= end_time <= 168h.
    ///
    bool closed_tickets_sorted;

    ///
    /// \brief closed_tickets_count
    ///
    /// @note Used internally for optimizations.
    int closed_tickets_count;

    ///
    /// \brief closed_tickets
    /// @todo: add comment
    ticket_t *closed_tickets[NUMBER_OF_TICKETS];

    ///
    /// \brief tariff_step_min
    ///
    /// @todo: add comment
    time_t tariff_step_min;

    ///
    /// \brief tariff_step_max
    ///
    /// @todo: add comment
    time_t tariff_step_max;

    ///
    /// \brief tariff_version
    /// Version for a given config-file, associated to a given tariff.
    char tariff_version[64];

    ///
    /// \brief free_of_charge_at_start;
    ///
    /// Free-of-charge minutes at beginning of tariff computation
    ///
    uint16_t free_of_charge_at_start;

    ///
    /// \brief repeated_default_without_carryover
    ///
    /// Setting describing a special tariff:
    /// - All days are equal
    /// - 24:00 is a "tariff-schnitt" (=without_carryover)
    /// (i.e. computation is carried out
    /// on a per day basis. Total price is the sum of all days.)
    bool repeated_default_without_carryover;

    ///
    /// \brief waiting_period
    /// @note Also called "Karenzzeit". Allowed values: [0, 3]
    minute_t waiting_period;
#endif
};

#endif // CALCULATE_PARKING_TICKETS_TARIFF_H_INCLUDED
