#pragma once

#include "Axis_State_Strategy.hpp"
#include "Axis_Builder.h"

#include <renderive/base/property/Attach_Builder.hpp>
#include <renderive/base/property/Property.hpp>
#include <deque>
#include <limits>
#include <utility>

namespace renderive {

struct Time_Axis_Properties : Axis_Base_Properties {
    Range_Value<int, 2, std::numeric_limits<int>::max()> visible_count{100};
    Range_Value<int, 0, std::numeric_limits<int>::max()> tick_label_spacing_px{8};
    std::string format = "mm:ss.zzz";
    bool newest_at_start{};
};

namespace detail {

struct Time_Axis_State : Time_Axis_Properties {
    int next_tick{};
    std::deque<std::pair<int, Time_Of_Day>> samples;
};

class LIB_DECL Time_Axis_Control : public Axis_State_Strategy<Time_Axis_State> {
public:
    explicit Time_Axis_Control(const Time_Axis_Properties& properties);
    [[nodiscard]] std::size_t time_point_count() const;
    int append_time(Time_Of_Day time);
    [[nodiscard]] Time_Of_Day tick_to_time(int tick) const;

private:
    [[nodiscard]] Range coordinate_range(const Time_Axis_State& state) const noexcept override;
    [[nodiscard]] double calculate_tick_step(Range range, const Time_Axis_State& state) const override;
    [[nodiscard]] std::string format_tick_label(double tick, const Time_Axis_State& state) const override;
};

} // namespace detail

using Time_Axis = Attach_Builder<detail::Time_Axis_Control, Time_Axis_Properties, detail::Axis_Renderable_Builder>;

} // namespace renderive
