#pragma once
#include <vector>
#include <string>
#include <memory>
// #include "cuda_hit_buffer.cuh"

namespace clustering
{
    namespace SoAClustering
    {
        template <typename hit_type>
        class extra_attribute_data;
    }
    using namespace SoAClustering;

    template <typename hit_type>
    struct cluster_attributes
    {
        const uint32_t *cluster_sizes;
        const float *energy;
        const float *cluster_energy;
        std::vector<float *> cluster_energy_2d_map;
        std::vector<uint32_t *> cluster_energy_2d_map_indices;

        const float *energy_2d_map;
        const uint32_t *energy_2d_map_indices;

        const uint32_t *cluster_energy_spectrum;
        const float *x_centroid;
        const float *y_centroid;
        const typename hit_type::compact_toa_type *cluster_start_toa;

        uint32_t cluster_count;
        uint32_t nonzero_pixel_matrix_count;
        std::vector<uint64_t> nonzero_pixel_matrix_count_clustered;
        /*cluster_attributes(extra_attribute_data<hit_type> *extra_data) : cluster_sizes(extra_data->cluster_sizes),
                                                                         energy(extra_data->energy),
                                                                         cluster_energy(extra_data->cluster_energy),
                                                                         cluster_energy_2d_map(),
                                                                         cluster_energy_2d_map_indices(),
                                                                         energy_2d_map(extra_data->energy_2d_map),
                                                                         energy_2d_map_indices(extra_data->energy_2d_map_indices),
                                                                         cluster_energy_spectrum(extra_data->cluster_energy_spectrum),
                                                                         x_centroid(extra_data->x_centroid),
                                                                         y_centroid(extra_data->y_centroid),
                                                                         cluster_start_toa(extra_data->cluster_start_toa)
        {
            cluster_count = extra_data->cluster_count_ptr ? *extra_data->cluster_count_ptr : 0;
            nonzero_pixel_matrix_count = extra_data->nonzero_pixel_matrix_count_ptr ? *extra_data->nonzero_pixel_matrix_count_ptr : 0;
            nonzero_pixel_matrix_count_clustered = extra_data->nonzero_pixel_matrix_count_clustered_ptr ? *extra_data->nonzero_pixel_matrix_count_clustered_ptr : 0;
        }*/

        cluster_attributes(extra_attribute_data<hit_type> *extra_data, const std::vector<uint32_t *> &cluster_energy_2d_map_indices_merged, const std::vector<float *> &cluster_energy_2d_map_merged, const std::vector<uint64_t> &nonzero_pixel_matrix_count_clustered_merged);
    };

    template <typename hit_type>
    struct clustered_data
    {
        using x_t = typename hit_type::x_type;
        using y_t = typename hit_type::y_type;
        using ctoa_t = typename hit_type::compact_toa_type;
        using tot_t = typename hit_type::tot_type;
        using toa_t = typename hit_type::toa_type;

    public:
        // clustered_data(x_t* x, y_t* y, toa_t* toa, tot_t* tot, uint32_t* label, uint64_t size):
        // x(x), y(y), toa(toa), tot(tot), label(label), size(size){}

        const x_t *x;
        const y_t *y;
        const ctoa_t *toa;
        const tot_t *tot;
        const uint32_t *label;
        const uint64_t size;
        const toa_t toa_offset;

        const cluster_attributes<hit_type> attributes;
        /*clustered_data(const x_t *x, const y_t *y,
                       const ctoa_t *toa, const tot_t *tot, const uint32_t *label,
                       uint64_t size, toa_t toa_offset, extra_attribute_data<hit_type> *attributes) : x(x),
                                                                                                      y(y),
                                                                                                      toa(toa),
                                                                                                      tot(tot),
                                                                                                      label(label),
                                                                                                      size(size),
                                                                                                      toa_offset(toa_offset),
                                                                                                      attributes(attributes)
        {
        }*/
        clustered_data(const x_t *x, const y_t *y,
                       const ctoa_t *toa, const tot_t *tot, const uint32_t *label,
                       uint64_t size, toa_t toa_offset, extra_attribute_data<hit_type> *attributes,
                       const std::vector<uint32_t *> &cluster_energy_2d_map_indices, std::vector<float *> &cluster_energy_2d_map,
                       std::vector<uint64_t> nonzero_pixel_matrix_count_clustered);
    };
}