#pragma once

#ifndef ALARM_TIMER_H_6018C1B0C87B40d3B5FB3A51326EBF17
#define ALARM_TIMER_H_6018C1B0C87B40d3B5FB3A51326EBF17

#include <functional>

#include <util/generic/noncopyable.h>

#include <wmconsole/legacy/util/event.h>

namespace NWebmaster {
class alarm_timer : public TNonCopyable {
public:
    typedef std::function<void()> t_proc_func;

    explicit alarm_timer(t_proc_func alarm_func) :
        ms(0),
        func(alarm_func),
        thr_func(std::bind(&alarm_timer::thr_alarm, this)) {
        eh_thrs.set_event<0>(close_ev);
        eh_stop_thrs.set_event<0>(thr_stop_ev);
    };

    template <typename t_thr_pool>
    void start(unsigned long ms, t_thr_pool &thrs) {
        if (0 == ms) {
            return;
        }

        close_ev.reset();
        thr_stop_ev.reset();
        this->ms = ms;
        thrs.add_task(thr_func);
    }

    void stop() {
        if (0 == ms) {
            return;
        }

        close_ev.set();
        eh_stop_thrs.wait_any();
    }

private:
    void thr_alarm() {
        if (0 != eh_thrs.wait_any(ms)) {
            try {
                func();
            } catch (...) {}
        }
        thr_stop_ev.set();
    }

    unsigned long ms;
    t_proc_func func;
    t_proc_func thr_func;

    threads::event close_ev;
    threads::event thr_stop_ev;
    threads::event_holder<1> eh_thrs;
    threads::event_holder<1> eh_stop_thrs;
};

struct alarm_timer_guard {
    template <typename t_thr_pool>
    alarm_timer_guard(alarm_timer &timer, unsigned long ms, t_thr_pool &thrs) : timer(timer) {
        timer.start(ms, thrs);
    }

    ~alarm_timer_guard() {
        timer.stop();
    }

private:
    alarm_timer &timer;
};

}

#endif
