// Davis Logic V2: DULLEA Ecosystem
// File: dullea_peak_to_peak.hpp
#ifndef DULLEA_PEAK_TO_PEAK_HPP
#define DULLEA_PEAK_TO_PEAK_HPP

#include "dullea_core_types.hpp"

namespace Dullea {
    /**
     * @brief Windowed Peak-to-Peak Amplitude and Extremum Tracking Core.
     * @tparam WindowPower Power of 2 defining the history buffer size.
     */
    template <size_t WindowPower = 4>
    class PeakToPeakDetector {
    public:
        static_assert(WindowPower > 0 && WindowPower < 12, "WindowPower must be between 1 and 11");
        
        static constexpr size_t WINDOW_SIZE = 1ULL << WindowPower;
        static constexpr size_t BIT_MASK = WINDOW_SIZE - 1;

        inline PeakToPeakDetector() : m_head(0), m_initialized(false) {
            reset();
        }

        /**
         * @brief Updates the history window and computes current peak-to-peak difference.
         * @param sample New fixed-point q15_16_t input value.
         * @return Peak-to-peak signal amplitude range (Max - Min).
         */
        inline q15_16_t update(q15_16_t sample) {
            if (!m_initialized) {
                for (size_t i = 0; i < WINDOW_SIZE; ++i) {
                    m_history[i] = sample;
                }
                m_initialized = true;
                return 0;
            }

            m_history[m_head] = sample;
            m_head = (m_head + 1) & BIT_MASK;

            // Search history window for current local extremums
            q15_16_t current_max = m_history[0];
            q15_16_t current_min = m_history[0];

            for (size_t i = 1; i < WINDOW_SIZE; ++i) {
                if (m_history[i] > current_max) current_max = m_history[i];
                if (m_history[i] < current_min) current_min = m_history[i];
            }

            return current_max - current_min;
        }

        inline void reset() {
            m_head = 0;
            m_initialized = false;
            for (size_t i = 0; i < WINDOW_SIZE; ++i) {
                m_history[i] = 0;
            }
        }

    private:
        size_t m_head;
        bool m_initialized;
        q15_16_t m_history[WINDOW_SIZE];
    };
}
#endif
