#include "calibration_master.hpp"

#include <stdexcept>

namespace radar::preprocessing {

CalibrationMaster::CalibrationMaster(std::unique_ptr<CalibratorInterface> s21_calibrator)
    : s21_calibrator_(std::move(s21_calibrator)) {
    if (!s21_calibrator_) {
        throw std::runtime_error("CalibrationMaster requires a non-null calibrator");
    }
}

void CalibrationMaster::load_s21_calibration_bundle(const std::string& path) {
    s21_calibration_bundle_.load(path);
}

void CalibrationMaster::load_s11_calibration_bundle(
    const std::string& open_path,
    const std::string& short_path,
    const std::string& load_path
) {
    s11_calibration_bundle_.load(open_path, short_path, load_path);
}

void CalibrationMaster::validate_combos(const std::vector<ipc::ComboKey>& combos) const {
    s21_calibration_bundle_.validate_combos(combos);
    s11_calibration_bundle_.validate_combos(combos);
}

auto CalibrationMaster::apply_to_trace(const ipc::SweepTraceBlock& measured_trace) const -> ipc::SweepTraceBlock {
    ipc::SweepTraceBlock output{};
    output.combo = measured_trace.combo;
    output.frequency_hz = measured_trace.frequency_hz;
    output.s21 = apply_s21(measured_trace.combo, measured_trace.frequency_hz, measured_trace.s21);
    output.s11 = apply_s11(measured_trace.combo, measured_trace.frequency_hz, measured_trace.s11);
    return output;
}

auto CalibrationMaster::apply_s21(
    const ipc::ComboKey& combo,
    std::span<const float> frequency_hz,
    const std::vector<ipc::Complex32>& measured_s21
) const -> std::vector<ipc::Complex32> {
    return s21_calibration_bundle_.apply(combo, frequency_hz, measured_s21, *s21_calibrator_);
}

auto CalibrationMaster::apply_s11(
    const ipc::ComboKey& combo,
    std::span<const float> frequency_hz,
    const std::vector<ipc::Complex32>& measured_s11
) const -> std::vector<ipc::Complex32> {
    return s11_calibration_bundle_.apply(combo, frequency_hz, measured_s11);
}

auto CalibrationMaster::has_s11_calibration() const noexcept -> bool {
    return s11_calibration_bundle_.is_enabled();
}

}  // namespace radar::preprocessing
