/**
 * @file Cosa/Alarm.hh
 * @version 1.0
 *
 * @section License
 * Copyright (C) 2014-2015, Mikael Patel
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * This file is part of the Arduino Che Cosa project.
 */

#ifndef COSA_ALARM_HH
#define COSA_ALARM_HH

#include "Cosa/Types.h"
#include "Cosa/Clock.hh"
#include "Cosa/Periodic.hh"
#include "Cosa/ExternalInterrupt.hh"

/**
 * The Alarm class is an extension of the Periodic job class. It allows
 * repeated jobs with seconds as time unit. The abstract Alarm Clock
 * is used as the alarm scheduler. It is triggered by an external
 * interrupt typically from an RTC device.
 */
class Alarm : public Periodic {
public:
  /**
   * Alarm Clock is an external interrupt based job scheduler. The
   * interrupt source should provide an interrupt every second to
   * update the seconds counter and dispatch expired alarms.
   */
  class Clock : public ::Clock, public ExternalInterrupt {
  public:
    /**
     * Construct Alarm Clock with given external interrupt pin, mode
     * and pullup flag. The external interrupt is assumed to be a 1 Hz
     * pulse generated by an external RTC module.
     * @param[in] pin external interrupt pin.
     * @param[in] mode pin mode (Default ON_RISING_MODE).
     * @param[in] pullup flag (Default false).
     */
    Clock(Board::ExternalInterruptPin pin,
	  InterruptMode mode = ON_RISING_MODE,
	  bool pullup = false) :
      ::Clock(),
      ExternalInterrupt(pin, mode, pullup)
    {}

  protected:
    /**
     * @override{Interrupt::Handler}
     * Increment the seconds counter and dispatch any expired alarms.
     * @param[in] arg argument from interrupt service routine (not used).
     */
    virtual void on_interrupt(uint16_t arg = 0)
    {
      UNUSED(arg);
      tick(1000);
    }
  };

  /**
   * Construct alarm with given clock and timeout period in seconds.
   * The clock should be a job scheduler with seconds as time unit.
   * @param[in] clock for alarms.
   * @param[in] period for alarm in seconds.
   */
  Alarm(::Clock* clock, uint32_t period) :
    Periodic(clock, period)
  {}
};
#endif

