/*
 * SPDX-FileCopyrightText: 2025 Copyright contributors to the cppTango project
 *
 * SPDX-License-Identifier: LGPL-3.0-or-later
 */
#ifndef TANGO_INTERNAL_EVENT_PERF_MONITOR_TIMEBLOCKMICROS_H
#define TANGO_INTERNAL_EVENT_PERF_MONITOR_TIMEBLOCKMICROS_H

#include <chrono>
#include <ratio>

namespace Tango
{

using PerfClock = std::chrono::steady_clock;

inline std::int64_t duration_micros(PerfClock::time_point start, PerfClock::time_point end)
{
    return std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
}

static constexpr const std::int64_t k_invalid_duration = std::numeric_limits<std::int64_t>::min();

struct TimeBlockMicros
{
    TimeBlockMicros() :
        TimeBlockMicros(false, nullptr)
    {
    }

    TimeBlockMicros(bool enabled, std::int64_t *slot) :
        enabled(enabled),
        slot(slot)
    {
        if(enabled)
        {
            start = PerfClock::now();
        }
    }

    TimeBlockMicros(const TimeBlockMicros &) = delete;
    TimeBlockMicros operator=(const TimeBlockMicros &) = delete;

    TimeBlockMicros &operator=(TimeBlockMicros &&other) noexcept
    {
        enabled = other.enabled;
        slot = other.slot;
        start = other.start;

        other.enabled = false;
        other.slot = nullptr;

        return *this;
    }

    TimeBlockMicros(TimeBlockMicros &&other) noexcept :
        enabled(other.enabled),
        start(other.start),
        slot(other.slot)
    {
        other.enabled = false;
        other.slot = nullptr;
    }

    ~TimeBlockMicros()
    {
        if(enabled)
        {
            PerfClock::time_point end = PerfClock::now();
            *slot += duration_micros(start, end);
        }
    }

    bool enabled;
    PerfClock::time_point start;
    std::int64_t *slot;
};
} // namespace Tango
#endif // TANGO_INTERNAL_EVENT_PERF_MONITOR_TIMEBLOCKMICROS_H
