#pragma once
#include "Hover_Tooltip.h"
#include "Plottable.h"
#include "../axis/Axis.h"
#include "../renderable/Render_Partition.h"
#include <renderive/renderable/Render_Frame_Completion.hpp>
#include <memory_resource>
#include <span>
#include <vector>
namespace renderive {
struct Spectrum_Properties : Hover_Tooltip_Properties {
    Nonnegative_Count frequency_point_size;
    Render_Partition_Mode partition_mode{Render_Partition_Mode::Automatic};
    Positive_Count partition_count;
    Range frequency_range{};
    double center_frequency = 50.0;
    Range sweep_frequency_range{40.0, 60.0};
    bool max_hold_visible{};
    bool min_hold_visible{};
    bool max_marker_visible{};
    bool use_min_marker{};
    bool sweep_region_visible{};
    bool visible_range_only{true};
    Line_Interpolation_Mode interpolation_mode = Line_Interpolation_Mode::Linear_Value;
    Brush max_brush;
    Brush current_brush;
    Brush min_brush;
    Pen max_pen{Color::red()};
    Pen current_pen{Color::green()};
    Pen min_pen{Color::white()};
    Pen selected_marker_pen{Color{0, 0, 139, 255}, 2.0};
    Pen marker_pen{Color::red()};
    Pen middle_frequency_pen{Color::red()};
    Brush sweep_region_brush{Color{255, 255, 0, 100}, Brush_Style::Solid};
};
namespace detail {
class LIB_DECL Spectrum_Control : public Plottable_State<Spectrum_Properties>,
                                  public Event_Handler,
                                  public ::Render_Frame_Completion {
public:
    Spectrum_Control(const Spectrum_Properties& properties, renderive_Owner<Frequency_Axis> frequency_axis, renderive_Owner<Axis> power_axis);
    ~Spectrum_Control() override;
    void update_samples(std::span<const double> values);
    void update_samples(std::pmr::vector<double>&& values);
    template <class Values>
    void update_samples(const Values& values) {
        update_samples(std::span<const double>(values.data(), values.size()));
    }
    [[nodiscard]] std::size_t sample_count() const;
    [[nodiscard]] std::size_t rendered_point_count() const;
    [[nodiscard]] double power_at(double frequency, bool& ok) const;
    void add_custom_marker(double frequency);
    void add_custom_line_marker(double frequency);
    void remove_custom_marker(double frequency);
    void remove_selected_marker();
    void clear_custom_markers();
    [[nodiscard]] int selectable_line_marker_count() const;
    [[nodiscard]] int selected_marker_index() const;
    void set_selected_marker_index(int index);
    void select_next_marker();
    void select_previous_marker();
    void clear_marker_selection();
    [[nodiscard]] double marker_frequency(int index) const;
    void set_marker_frequency(int index, double frequency);
    void set_current_marker_frequency(double frequency);
    void handle_event(const Event& event) override;
protected:
    void prepare_frame(const Prepare_Render_Context& context) override;
    void paint(Painter& painter, const Paint_Render_Context& context) override;
    void build_prepare_graph(Renderable_Graph_Builder& builder) override;
    void build_paint_graph(Renderable_Graph_Builder& builder) override;
private:
    struct Impl;
    void prepare_render_frame(const Render_State_View& state, int graph_partition_count);
    void prepare_partition(int partition_index);
    void paint_partition(Painter& painter, int partition_index,
                         const Render_State_View& state);
    void paint_background(Painter& painter, const Render_State_View& state);
    void paint_overlay(Painter& painter, const Render_State_View& state);
    void render_frame_completed(std::uint64_t target_interval_ns) override;
    void publish() override;
};
}
using Spectrum = detail::Attach_Plottable<detail::Spectrum_Control, Spectrum_Properties>;
}
