// SPDX-License-Identifier: LGPL-3.0-or-later
// Copyright (C) 2024-2025 Simon Gardner, Chun Yuen Tsang, Prithwish Tribedy,
//                         Minho Kim, Sylvester Joosten, Wouter Deconinck, Dmitry Kalinkin
//
// Convert energy deposition into analog pulses

#pragma once

#include <algorithms/algorithm.h>
#include <edm4eic/SimPulseCollection.h>
#include <edm4eic/unit_system.h>
#include <edm4hep/SimCalorimeterHitCollection.h>
#include <edm4hep/SimTrackerHitCollection.h>
#include <memory>
#include <string_view>
#include <tuple>
#include <variant>

#include "algorithms/digi/PulseGenerationConfig.h"
#include "algorithms/interfaces/WithPodConfig.h"

namespace eicrecon {

using PulseType        = edm4eic::SimPulse;
using MutablePulseType = edm4eic::MutableSimPulse;

template <typename HitT> struct HitAdapter;

template <> struct HitAdapter<edm4hep::SimTrackerHit> {
  static std::tuple<double, double> getPulseSources(const edm4hep::SimTrackerHit& hit);
  static void addRelations(MutablePulseType& pulse, const edm4hep::SimTrackerHit& hit);
};

template <> struct HitAdapter<edm4hep::SimCalorimeterHit> {
  static std::tuple<double, double> getPulseSources(const edm4hep::SimCalorimeterHit& hit);
  static void addRelations(MutablePulseType& pulse, const edm4hep::SimCalorimeterHit& hit);
};

template <typename HitT>
using PulseGenerationAlgorithm =
    algorithms::Algorithm<algorithms::Input<typename HitT::collection_type>,
                          algorithms::Output<PulseType::collection_type>>;

class SignalPulse;

template <typename HitT>
class PulseGeneration : public PulseGenerationAlgorithm<HitT>,
                        public WithPodConfig<PulseGenerationConfig> {

public:
  PulseGeneration(std::string_view name)
      : PulseGenerationAlgorithm<HitT>{name, {"RawHits"}, {"OutputPulses"}, {}} {}
  void init() final;
  void process(const typename PulseGenerationAlgorithm<HitT>::Input&,
               const typename PulseGenerationAlgorithm<HitT>::Output&) const final;

private:
  std::shared_ptr<SignalPulse> m_pulse;
  float m_min_sampling_time = 0 * edm4eic::unit::ns;
};

} // namespace eicrecon
