//-------------------------------------------------------------------------------
// <copyright file="PPPHostSettings.h" company="LiquidRobotics">
//
// Copyright (c) 2014 Liquid Robotics, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// This software is associated with a release.  Liquid Robotics makes no
// representation that the design, interfaces or component distribution will
// remain unchanged in future releases.
//
// </copyright>
//
// <summary>
//   Declarations for the PPPHostSettings class, a serializable entity class that
//   contains the configuration settings for the PPPHost class.
// </summary>
//
// <owner>Mike Cookson</owner>
//-------------------------------------------------------------------------------

#ifndef __PPPHOSTSETTINGS_H__
#define __PPPHOSTSETTINGS_H__

#include "LqrSMACSerialPortSettings.h"
#include "LqrSMACSharedLib.h"
#include <ostream>
#include <string>
#include <boost/serialization/access.hpp>
#include <boost/serialization/nvp.hpp>

namespace LiquidRobotics {
namespace PPPHostLib {

class SHARED_LIB_PUBLIC PPPHostSettings
{
public:

	typedef LiquidRobotics::SMACFramework::SerialPortSettings SerialPortSettings;
	typedef std::string string;

	PPPHostSettings();
	//PPPHostSettings(const SerialPortSettings& _spSettings);
	PPPHostSettings(const PPPHostSettings& other);

	virtual ~PPPHostSettings();

	PPPHostSettings& operator=(const PPPHostSettings& other);
	bool operator==(const PPPHostSettings& other) const;

	// The dialup timeout is the number of seconds for the dialer to wait
	// for a connection message in the case that a phone number has been
	// provided
	const float GetDialupTimeoutSeconds() const;
	void SetDialupTimeoutSeconds(float newValue);

	// The modem response timeout is the number of seconds to wait for each
	// command response
	const float GetModemResponseTimeoutSeconds() const;
	void SetModemResponseTimeoutSeconds(float newValue);

	// The modem registration timeout is the number of seconds to wait
	// for the modem to connect to the Iridium network (CREG)
	const float GetModemRegistrationTimeoutSeconds() const;
	void SetModemRegistrationTimeoutSeconds(float newValue);

	// The phone number, if not blank, is used to call the Iridium
	// gateway; if it is blank, the DIALING phase is skipped and the
	// PPP interface program is called, which must do any connection
	// that is necessary
	const string& GetPhoneNumber() const;
	void SetPhoneNumber(const string& newValue);

	// The power off delay is the number of seconds to wait in the
	// DISCONNECTING state after power-off before transition to
	// DISCONNECTED state
	float GetPowerOffDelaySeconds() const;
	void SetPowerOffDelaySeconds(float newValue);

	// The power on delay is the number of seconds to wait after power
	// is applied before communicating with the modem
	float GetPowerOnDelaySeconds() const;
	void SetPowerOnDelaySeconds(float newValue);

	// This is the command that, if provided, is sent to remove power
	// from the modem; if the command is blank, the power off time
	// is not used
	const string& GetPowerOffVerb() const;
	void SetPowerOffVerb(const string& newValue);

	// This is the command that, if provided, is sent to apply power
	// to the modem; if the command is blank, the power on time is
	// not used
	const string& GetPowerOnVerb() const;
	void SetPowerOnVerb(const string& newValue);

	// This is the command that is executed after powering on, initializing
	// the modem and dialing the number (if the number was provided); it
	// is expected to run the PPP service and dial if no number was provided
	const string& GetProtocolDaemonVerb() const;
	void SetProtocolDaemonVerb(const string& newValue);

	// The number of times a command is sent without a good response before
	// failing
	unsigned GetSendTries() const;
	void SetSendTries(unsigned newValue);

	// The size of internal event queues
	unsigned GetQueueCapacity() const;
	void SetQueueCapacity(unsigned newValue);

	// These are the settings for the serial port
	const SerialPortSettings& GetSerialPortSettings() const;
	void SetSerialPortSettings(const SerialPortSettings& newValue);

	// Operations to deserialize from (Load) or serialize to (Save) a
	// storage file; in the case of Load, if the file length is 0, the
	// file is overwritten with some example data
	void Load(const string& fileName);
	void Save(const string& fileName);

private:

	// The serialize function is used by the Boost serialization library
	// to save or load member variables from an Archive object; leaving
	// the function in the header file as a template method allows for
	// various archives to be used.
	friend class boost::serialization::access;

	template<class Archive>
	void serialize(Archive& ar, const unsigned int version)
	{
		ar & BOOST_SERIALIZATION_NVP(dialupTimeout);
		ar & BOOST_SERIALIZATION_NVP(modemRegistrationTimeout);
		ar & BOOST_SERIALIZATION_NVP(modemResponseTimeout);
		ar & BOOST_SERIALIZATION_NVP(phoneNumber);
		ar & BOOST_SERIALIZATION_NVP(powerOffDelay);
		ar & BOOST_SERIALIZATION_NVP(powerOnDelay);
		ar & BOOST_SERIALIZATION_NVP(powerOffVerb);
		ar & BOOST_SERIALIZATION_NVP(powerOnVerb);
		ar & BOOST_SERIALIZATION_NVP(protocolDaemonVerb);
		ar & BOOST_SERIALIZATION_NVP(sendTries);
		ar & BOOST_SERIALIZATION_NVP(queueCapacity);
		ar & BOOST_SERIALIZATION_NVP(spSettings);

		CheckValues();
	}

	void CheckValues() const;

	float dialupTimeout;						// the number of seconds to wait for a connect when dialing (if phone number provided)
	float modemRegistrationTimeout;				// the number of seconds to wait for the modem to connect to the Iridium network
	float modemResponseTimeout;					// the number of seconds to wait for responses from the modem
	string phoneNumber;							// the phone number to call or blank if the protocol daemon will establish connection
	float powerOffDelay;						// the number of seconds to wait in the DISCONNECTING state after turning power off
	float powerOnDelay;							// the number of seconds to wait after turning power on before communicating with the modem
	string powerOffVerb;						// the command to execute to turn modem power off (or blank if feature not enabled)
	string powerOnVerb;							// the command to execute to turn modem power on (or blank if feature not enabled)
	string protocolDaemonVerb;					// the command to execute to start the protocol daemon: must not be blank
	unsigned sendTries;							// the number of times a command is sent without a good response before failing
	unsigned queueCapacity;						// the maximum number of elements in queues
	SerialPortSettings spSettings;				// the settings for the serial port
};

SHARED_LIB_PUBLIC std::ostream& operator<<(std::ostream& out, const PPPHostSettings& settings);

}
}

#endif /* PPPHOSTSETTINGS_H_ */
