/* Network-Integrated Multimedia Middleware (NMM)
 * http://www.motama.com/nmm.html
 *
 * Copyright (C) 2006-2007
 * Motama GmbH, Saarbruecken, Germany
 * http://www.motama.com
 *
 * This file is part of NMM. 
 * 
 * NMM is free software; you can redistribute it and/or modify it    
 * under the terms of the GNU General Public License as published by 
 * the Free Software Foundation; only version 2 of the License.      
 * 
 * NMM 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 General Public 
 * License for more details.  
 * 
 * You should have received a copy of the GNU General Public License 
 * along with NMM; if not, write to the Free Software Foundation,    
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#ifndef NMM_IDelayMeasurementImpl_HPP
#define NMM_IDelayMeasurementImpl_HPP

#include "nmm/nmm_prefix.hpp"

#include "nmm/comm/NMMObject.hpp"
#include "IDelayMeasurement.hpp"


#include "visibility.hpp"

namespace NMM
{
  /** Interface for flowgraph delay measurement control.
   *
   * This interface is implemented by all nodes for getting/setting delay measurement parameters.
   * Any node may start or stop delay measurement. Delay measurement is started by measuring the current
   * system time and setting the delay start time of a message. Delay measurement is stopped by measuring
   * the current system time and computing the different to the delay start time of a message. The result
   * is called the delay of the message.
   *
   * The result is logged as a LOGDELAY message. In addition to that, an average over all messages is computed
   * and also logged as a LOGDELAY message. The LOGDELAY stream must be activated for the message to be displayed.
   * The number of messages after which a log message is displayed can also be set.
   *
   * Every node can start or stop measurement at a certain timepoint. Timepoints for starting delay measurement are
   *
   * - when creating a new message
   * - when sending a message
   * - when receiving a message
   * - when dequeueing a message
   *
   * Timepoints for stopping delay measurement
   *
   * - when sending a message
   * - when receiving a message
   * - when dequeueing a message
   * - when presenting a message (synchronized sink nodes only)
   *
   * Starting and stopping delay measurement can be enabled for at most one timepoint at every node using this
   * interface. Furthermore, this interface provides methods for resetting delay measurement, querying the current
   * average message delay and setting the number of samples for average computation.
   *
   * Example 1: Measure the internal delay of a (not source) node
   * @code
   * IDelayMeasurement delay(node->getParentObject()->getCheckedInterface<IDelayMeasurement>());
   * delay->setDelayStartEnabled(IDelayMeasurement::START_WITH_DEQUEUE_MESSAGE, true);
   * delay->setDelayStopEnabled(IDelayMeasurement::STOP_WITH_SEND_MESSAGE, true);
   * @endcode
   *
   * Example 2: Measure the network delay between two nodes
   * @code
   * IDelayMeasurement delay1(node1->getParentObject()->getCheckedInterface<IDelayMeasurement>());
   * IDelayMeasurement delay2(node2->getParentObject()->getCheckedInterface<IDelayMeasurement>());
   * delay1->setDelayStartEnabled(IDelayMeasurement::START_WITH_SEND_MESSAGE, true);
   * delay2->setDelayStopEnabled(IDelayMeasurement::STOP_WITH_RECEIVE_MESSAGE, true);
   * @endcode
   *
   * Example 3: Measure the delay of the queue of a node
   * @code
   * IDelayMeasurement delay(node->getParentObject()->getCheckedInterface<IDelayMeasurement>());
   * delay->setDelayStartEnabled(IDelayMeasurement::START_WITH_RECEIVE_MESSAGE, true);
   * delay->setDelayStopEnabled(IDelayMeasurement::START_WITH_DEQUEUE_MESSAGE, true);
   * @endcode
   *
   * Example 4: Measure the total delay of a graph from source to sink
   * @code
   * IDelayMeasurement delay_source(source->getParentObject()->getCheckedInterface<IDelayMeasurement>());
   * IDelayMeasurement delay_sink(sink->getParentObject()->getCheckedInterface<IDelayMeasurement>());
   * delay_source->setDelayStartEnabled(IDelayMeasurement::START_WITH_NEW_MESSAGE, true);
   * delay_sink->setDelayStopEnabled(IDelayMeasurement::STOP_WITH_PRESENT_MESSAGE, true);
   * @endcode
   *
   * The interface also provides methods for use in clic which accept strings instead of
   * enum values. For usage examples, see the directory apps/clic/gd/delay.
   *
   * By default, delay measurement is disabled and the number of samples is 10.
   * Delqy logging is disabled, and when enabled, the default logging interval is every 20 messages.
   */

  class DLLEXPORT IDelayMeasurementImpl  : public virtual NMM::NMMObject { 
  public:
    IDelayMeasurementImpl() { addInterface(new IDelayMeasurement(*this)); registerEvents(); };

    virtual ~IDelayMeasurementImpl() {};

  protected:
    /** Enable or disable a start timepoint for delay measurement.
     *
     * This method enables or disables starting delay measurement for this node at the given time point.
     *
     * @param start_timepoint The start timepoint for delay measurement
     * @param enabled @c true to enable or @c false to disable delay measurement
     */

    virtual void setDelayStartEnabled(const IDelayMeasurement::StartTimepoint& start_timepoint, const nmm_bool& enabled) = 0;
    /** Enable or disable a stop timepoint for delay measurement.
     *
     * This method enables or disables stopped delay measurement for this node at the given time point.
     *
     * @param stop_timepoint The stop timepoint for delay measurement
     * @param enabled @c true to enable or @c false to disable delay measurement
     */

    virtual void setDelayStopEnabled(const IDelayMeasurement::StopTimepoint& stop_timepoint, const nmm_bool& enabled) = 0;
    /** Enable or disable a start timepoint for delay measurement (clic interface).
     *
     * This method enables or disables starting delay measurement for this node at the given time point.
     *
     * @param start_timepoint The start timepoint for delay measurement
     * @param enabled @c true to enable or @c false to disable delay measurement
     *
     * @deprecated Helper method which becomes obsolete when clic can handle enum values
     */

    virtual void setDelayStartEnabled2(const string& start_timepoint, const nmm_bool& enabled) = 0;
    /** Enable or disable a stop timepoint for delay measurement (clic interface).
     *
     * This method enables or disables stopped delay measurement for this node at the given time point.
     *
     * @param stop_timepoint The stop timepoint for delay measurement
     * @param enabled @c true to enable or @c false to disable delay measurement
     *
     * @deprecated Helper method which becomes obsolete when clic can handle enum values
     */

    virtual void setDelayStopEnabled2(const string& stop_timepoint, const nmm_bool& enabled) = 0;
    /** Check if a start timepoint for delay measurement is enabled.
     *
     * @param start_timepoint The start timepoint for delay measurement
     * @return @c true if delay measurement is enabled, otherwise @c false
     */

    virtual nmm_bool isDelayStartEnabled(const IDelayMeasurement::StartTimepoint& start_timepoint) const = 0;
    /** Check if a stop timepoint for delay measurement is enabled.
     *
     * @param stop_timepoint The stop timepoint for delay measurement
     * @return @c true if delay measurement is enabled, otherwise @c false
     */

    virtual nmm_bool isDelayStopEnabled(const IDelayMeasurement::StopTimepoint& stop_timepoint) const = 0;
    /** Get average message delay.
     *
     * This method returns the current average over the last measured delays.
     * The result is valid only if the stop timepoint is not @c NO_STOP and the node has
     * already received messages.
     *
     * @param stop_timepoint The stop timepoint for delay measurement
     * @return The average message delay
     */

    virtual Interval getAverageDelay(const IDelayMeasurement::StopTimepoint& stop_timepoint) = 0;
    /** Get minimum message delay.
     *
     * This method returns the current minimum over the last measured delays.
     * The result is valid only if the stop timepoint is not @c NO_STOP and the node has
     * already received messages.
     *
     * @param stop_timepoint The stop timepoint for delay measurement
     * @return The minimum message delay
     */

    virtual Interval getMinDelay(const IDelayMeasurement::StopTimepoint& stop_timepoint) = 0;
    /** Get maximum message delay.
     *
     * This method returns the current maximum over the last measured delays.
     * The result is valid only if the stop timepoint is not @c NO_STOP and the node has
     * already received messages.
     *
     * @param stop_timepoint The stop timepoint for delay measurement
     * @return The maximum message delay
     */

    virtual Interval getMaxDelay(const IDelayMeasurement::StopTimepoint& stop_timepoint) = 0;
    /** Reset delay measurement for this node.
     *
     * This method resets all samples of measured message delays for this node.
     *
     * @param stop_timepoint The stop timepoint for delay measurement
     */

    virtual void resetDelayMeasurement(const IDelayMeasurement::StopTimepoint& stop_timepoint) = 0;
    /** Set the number of samples for average delay computation.
     *
     * This method sets the maximum number of samples for computing the average message delay.
     * The delays of the most recent messages are stored up the the given number of messages
     * and used for computing a new average for every new message.
     *
     * @param number_of_samples The number of samples
     */

    virtual void setNumberOfDelaySamples(const nmm_uint32& number_of_samples) = 0;
    /** Enable or disable delay logging.
     *
     * @param enabled @c true to enable or @c false to disable delay logging
     */

    virtual void setDelayLoggingEnabled(const nmm_bool& enabled) = 0;
    /** Set delay logging interval.
     *
     * This method sets the number of messages after which a delay log message is displayed.
     * The default is to display a log message every 20 messages.
     *
     * @param interval The delay logging interval in number of messages
     */

    virtual void setDelayLoggingInterval(const nmm_uint32& interval) = 0;


  private:
    void registerEvents();
  };

}

#include "nmm/nmm_suffix.hpp"

#endif
