//----------------------------------------------------------------------------------
// <copyright file="Alarm.h" company="LiquidRobotics">
//	Copyright (c) Liquid Robotics Corporation.  All rights reserved.
// </copyright>
//
// <summary>
//	Alarm Interface. Will send a telemetry message to shore.
// </summary>
//
// <owner>Andrew Trapani</owner>
//----------------------------------------------------------------------------------

#ifndef __EventLib_AlarmReporter_H__
#define __EventLib_AlarmReporter_H__

#include "EventTransceiver.h"
#include "LqrSMACIdl.h"
#include "LqrSMACSharedLib.h"
#include "LqrSMACAddressableMessageServiceBase.h"
#include "AlarmMessage.h"
#include "AlarmReporterSettings.h"
#include "AlarmSettings.h"
#include "SensorProgram.h"
#include <boost/multiprecision/cpp_int.hpp>
//FYI: This include does not work without installing whatever "GMP" is for "gmp.h"
//https://gmplib.org/
//It would run faster according to boost documentation.
//#include <boost/multiprecision/gmp.hpp>

namespace LiquidRobotics {
namespace EventLib {

class SHARED_LIB_PUBLIC AlarmReporter
{
	typedef std::string string;
	typedef LiquidRobotics::EventLib::EventTransceiver EventTransceiver;
	typedef LiquidRobotics::SMACFramework::IObjectBroker IObjectBroker;
	typedef LiquidRobotics::SMACFramework::Logger Logger;
	typedef boost::multiprecision::cpp_int cpp_int;
public:
	typedef boost::shared_ptr<AlarmReporter> AlarmReporterPtr;

	AlarmReporter(PayloadManagerClient::Ptr _pmClient, AlarmSettings& _alarmSettings,
			EventTransceiver& _eventTrasnceiver, IObjectBroker& _broker, Logger& _logger);

	/* These functions send a comment or alarm to WGMS */
	void sendAlarmWithType(const alarmTypes alarmType, const int notificationId, const string& message);
	void sendAlarmWithType(const alarmTypes alarmType, const timeval& timestamp,
			const int notificationId, const string& message);
	void sendAlarmWithType(const alarmTypes alarmType, const double latitude, const double longitude,
				const int notificationId, const string& message);
	void sendAlarmWithType(const alarmTypes alarmType, const double latitude, const double longitude,
			const timeval& timestamp, const int notificationId, const string& message);

	/* Report a predefined event as a comment. */
	void ReportEvent(const int notificationId, const string& message);
	void ReportEvent(const timeval& timestamp,
			const int notificationId, const string& message);
	void ReportEvent(const double latitude, const double longitude, const timeval& timestamp,
			const int notificationId, const string& message);

	/* Report a predefined alarm. Set the red light. */
	void ReportAlarm(const int notificationId, const string& message);
	void ReportAlarm(const timeval& timestamp,
			const int notificationId, const string& message);
	void ReportAlarm(const double latitude, const double longitude, const timeval& timestamp,
			const int notificationId, const string& message);

	/* Set a predefined alarm and remember it. Set the red light. */
	void SetAlarm(const int notificationId, const string& message);
	void SetAlarm(const timeval& timestamp,
			const int notificationId, const string& message);
	void SetAlarm(const double latitude, const double longitude, const timeval& timestamp,
			const int notificationId, const string& message);

	/* Clear a predefined alarm. Turn the red light yellow.  */
	void ClearAlarm(const int notificationId);
	void ClearAlarm(const timeval& timestamp,  const int notificationId);
	void ClearAlarm(const double latitude, const double longitude, const timeval& timestamp,
			 const int notificationId);

private:

	void CreateAndSendAlarmMessage(const double latitude, const double longitude, const timeval& timestamp,
			const alarmTypes alarmType, const int notificationId, const string& message);

	cpp_int GetUniqueId(const int reporterTypeId, const int enumerationType,
			const int notificationId);
	bool CheckAlarm(const alarmTypes alarmType, const int reporterTypeId, const int enumerationType,
			const int notificationId);
	bool CheckSetAlarmsForUniqueId(cpp_int uniqueId, bool setTo);
	bool CheckOneTimeAlarmsForUniqueId(cpp_int uniqueId);


	IObjectBroker& broker;
	EventTransceiver& eventTransceiver;
	PayloadManagerClient::Ptr pmClient;
	AlarmSettings& alarmSettings;
	Logger& logger;
	//Keep track of which alarms are set and clear so we don't double send the same message
	std::map <cpp_int,bool> setAndClearedAlarms;
	//Keep track of which one time alarms and events have been sent
	//Don't send them more than once per time limit, if the time limit is > 0
	timeval timeLimit;
	std::map <cpp_int,timeval> alarmTracker;
};

}
}

#endif
