#include <rapidjson/document.h>
#include <rapidjson/filereadstream.h>

#include <cstdio>
#include <string>
#include <vector>
#include <iomanip>

#define INPUTS_FILE "inputs.json"
/// @brief Pay attention to this strange number, you could tear your hairs out
#define JSON_BUFFER_SIZE 65536

using namespace rapidjson;

class Inputs {
    /// @brief RapidJSON
    Document d;
    /// @brief Current node associated with the Inputs
    std::string node_name;
    /// @brief Timestamps (at which time the nodes should wake up)
    std::vector<double> wake_ts;
    /// @brief Wake up time durations
    std::vector<double> wake_duration;
    /**
     * Recursively merge overlapping events
     */ 
    void MergeEvents();
public:
    /**
     * Load node_name configuration
     */
    Inputs(std::string node_name);
    /**
     * Generate a SimGrid platform file from the json configuration
     */
    static void GeneratePlatform(std::string p);
    /**
     * Is there any event that remains in the queue ?
     */
    bool ShouldContinue(){return wake_ts.size()!=0;}
    /**
     * Is there another event to process ?
     */
    bool HasNext(){return wake_ts.size()>1 ;}
    /**
     * Get current event timestamp
     */
    double GetTS(){return wake_ts.front();}
    /**
     * Get current event duration
     */
    double GetDuration(){return wake_duration.front();}
    /**
     * Get next event timestamp
     */
    double GetNextTS();
    /**
     * Get next event duration
     */
    double GetNextDuration();
    /**
     * Time travel machine (note that this function is following the second principle
     * of thermodynamics)
     */
    void GotoNextEvent();
    /**
     * Allows to add a *FUTURE* event and merge overlapping events
     */
    void AddEvent(double ts, double duration);
    /**
     * This is the timeline
     */
    void DumpEvents();

    /// @brief These are public attributes, please take care they are fragile
    bool is_sender;
    bool use_hint;
    bool extended;
    int data_size;
    int hint_size;
    int seed;
    int n_nodes;
    double latency;
};