//-------------------------------------------------------------------------------
// <copyright file="SSQCommunicatorSettings.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 SSQCommunicatorSettings class, a serializable entity that
// contains the settings for SSQCommunicator.
// </summary>
//
// <owner>Mike Cookson</owner>
//-------------------------------------------------------------------------------

#ifndef __SSQCOMMUNICATORSETTINGS_H__
#define	__SSQCOMMUNICATORSETTINGS_H__

#include "LqrSMACBooleanParser.h"
#include "LqrSMACSharedLib.h"
#include "SBDModemSettings.h"
#include <string>
#include <boost/serialization/access.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/split_member.hpp>
#include <boost/serialization/version.hpp>

namespace LiquidRobotics {
namespace SimpleSBDQueue {

class SHARED_LIB_PUBLIC SSQCommunicatorSettings
{
public:

    typedef std::string string;
    typedef LiquidRobotics::PPPHostLib::SBDModemSettings SBDModemSettings;

    //! Default constructor for the SSQCommunicatorSettings class (initializes settings with default values)
    SSQCommunicatorSettings();

    //! Copy constructor for SSQCommunicatorSettings class
    SSQCommunicatorSettings(const SSQCommunicatorSettings& orig);

    //! Destructor for SSQCommunicatorSettings class
    virtual ~SSQCommunicatorSettings();

    //! Returns the SBD modem settings
    const SBDModemSettings& GetSBDModemSettings() const;

    //! Sets a new value for the SBD modem settings
    void SetSBDModemSettings(const SBDModemSettings& newValue);

    //! Returns the minimum time that the modem must remain off once it has been turned off (in milliseconds)
    unsigned GetMinOffTimeMS() const;

    //! Sets the minimum time that the modem must remain off once it has been turned off (in milliseconds)
    void SetMinOffTimeMS(unsigned newValue);

    //! Returns the maximum time that the modem can remain on (in milliseconds. 0=no limit)
    unsigned GetMaxOnTimeMS() const;

    //! Sets the maximum time that the modem can remain on (in milliseconds, 0=no limit)
    void SetMaxOnTimeMS(unsigned newValue);

    //! Returns a flag that indicates whether the modem is turned off when not in use (true) or if it is left on all the time (false)
    bool GetDutyCycleModem() const;

    //! Sets the flag that indicates whether the modem is turned off when not in use (true) or if it is left on all the time (false)
    void SetDutyCycleModem(bool newValue);

    //! Returns the maximum time to wait for network available after powering on (in milliseconds, 1 minute default)
    unsigned GetNetworkAvailableTimeoutMS() const;

    //! Sets the maximum time to wait for network available after power on (in milliseconds, 1 minute default)
    void SetNetworkAvailableTimeoutMS(unsigned newValue);

    //! Returns the maximum time to wait between sessions (in milliseconds, 5 minute default)
    unsigned GetMailboxCheckIntervalMS() const;

    //! Sets the maximum time to wait between sessions (in milliseconds, 5 minute default)
    void SetMailboxCheckIntervalMS(unsigned newValue);

    //! Returns the delay to add after turning on the modem (in milliseconds, default 25 seconds)
    unsigned GetModemPowerOnDelayMS() const;

    //! Sets the delay to add after turning on the modem (in milliseconds, default 25 seconds)
    void SetModemPowerOnDelayMS(unsigned newValue);

    //! Returns the time to wait after a network failure (in milliseconds, 8 minute default)
    unsigned GetNetworkFailDelayMS() const;

    //! Sets the time to wait after a network failure (in milliseconds, 8 minute default)
    void SetNetworkFailDelayMS(unsigned newValue);

    //! Returns the time to wait after a communication failure or access denied (in milliseconds, 15 minute default)
    unsigned GetCommFailureDelayMS() const;

    //! Sets the time to wait after a communication failure or access denied (in milliseconds, 15 minute default)
    void SetCommFailureDelayMS(unsigned newValue);

    //! Returns a flag the indicates if ring indication is used when duty cycling is off (true), or if mailbox checks are always used (false)
    bool GetUseRingIndicator() const;

    //! Sets a flag that indicates if ring indication is used when duty cycling is off (true), or if mailbox checks are always used (false)
    void SetUseRingIndicator(bool newValue);

    //! Returns the command string that is executed to turn power on to the modem (blank=no command)
    string GetPowerOnVerb() const;

    //! Sets the command string that is executed to turn power on to the modem (blank=no command)
    void SetPowerOnVerb(const string& newValue);

    //! Returns the command string that is executed to turn power off to the modem (blank=no command)
    string GetPowerOffVerb() const;

    //! SeSts the command string that is executed to turn power off to the modem (blank=no command)
    void SetPowerOffVerb(const string& newValue);

    unsigned GetNetworkTimeoutSeconds() const;
    void SetNetworkTimeoutSeconds(unsigned newValue);
    
    //! Returns the flag that indicates whether to wait for network registration before proceeding (95XX only)
    bool GetWaitForNetworkRegistration() const;

    //! Sets the flag that indicates whether to wait for network registration before proceeding (95XX only)
    void SetWaitForNetworkRegistration(bool newValue = true);

    //! Loads settings from the given XML file
    void Load(const string& fileName);

    //! Saves the settings to the given XML file
    void Save(const string& fileName);

private:

    friend class boost::serialization::access;

    template<class Archive>
    void save(Archive& ar, const unsigned int version) const
    {
        using namespace LiquidRobotics::SMACFramework::BooleanParser;
        ar & BOOST_SERIALIZATION_NVP(sbdModemSettings);					// 1
        ar & BOOST_SERIALIZATION_NVP(minOffTimeMS);					// 1
        ar & BOOST_SERIALIZATION_NVP(maxOnTimeMS);					// 1
        save_boolean_to_archive(ar, dutyCycleModem, "dutyCycleModem");			// 1
        ar & BOOST_SERIALIZATION_NVP(networkAvailableTimeoutMS);			// 1
        ar & BOOST_SERIALIZATION_NVP(mailboxCheckIntervalMS);				// 1
        ar & BOOST_SERIALIZATION_NVP(networkFailDelayMS);				// 1
        ar & BOOST_SERIALIZATION_NVP(commFailureDelayMS);				// 1
        save_boolean_to_archive(ar, useRingIndicator, "useRingIndicator");		// 1
        ar & BOOST_SERIALIZATION_NVP(powerOnVerb);					// 1
        ar & BOOST_SERIALIZATION_NVP(powerOffVerb);					// 1
	ar & BOOST_SERIALIZATION_NVP(networkTimeoutSeconds);
        ar & BOOST_SERIALIZATION_NVP(modemOnDelayMS);					// 2
        save_boolean_to_archive(ar, waitForNetworkRegistration, "waitForNetworkRegistration"); // 2
    }

    template<class Archive>
    void load(Archive& ar, const int version)
    {
        using namespace LiquidRobotics::SMACFramework::BooleanParser;
        ar & BOOST_SERIALIZATION_NVP(sbdModemSettings);
        ar & BOOST_SERIALIZATION_NVP(minOffTimeMS);
        ar & BOOST_SERIALIZATION_NVP(maxOnTimeMS);
        load_boolean_from_archive(ar, dutyCycleModem, "dutyCycleModem");
        ar & BOOST_SERIALIZATION_NVP(networkAvailableTimeoutMS);
        ar & BOOST_SERIALIZATION_NVP(mailboxCheckIntervalMS);
        ar & BOOST_SERIALIZATION_NVP(networkFailDelayMS);
        ar & BOOST_SERIALIZATION_NVP(commFailureDelayMS);
        load_boolean_from_archive(ar, useRingIndicator, "useRingIndicator");
        ar & BOOST_SERIALIZATION_NVP(powerOnVerb);
        ar & BOOST_SERIALIZATION_NVP(powerOffVerb);
	ar & BOOST_SERIALIZATION_NVP(networkTimeoutSeconds);

        if (version >= 2)
        {
            ar & BOOST_SERIALIZATION_NVP(modemOnDelayMS);
            load_boolean_from_archive(ar, waitForNetworkRegistration, "waitForNetworkRegistration");
        }
    }

    BOOST_SERIALIZATION_SPLIT_MEMBER()

    SBDModemSettings sbdModemSettings;          //!< settings for the SBDModem class
    unsigned minOffTimeMS;                      //!< Once powered off, the minimum amount of time that the modem must stay off (in milliseconds, default 30 seconds)
    unsigned maxOnTimeMS;                       //!< Once powered on, the maximum amount of time that the modem can stay on (in milliseconds, 0=unlimited, 0 is default)
    bool dutyCycleModem;                        //!< Determines if the modem is duty cycled (true) or if it typically remains on (false); the default is true
    unsigned networkAvailableTimeoutMS;         //!< The maximum time to wait for a good signal (in milliseconds, 1 minute default)
    unsigned mailboxCheckIntervalMS;            //!< Maximum time between sessions if no errors (in milliseconds, default 5 minutes)
    unsigned networkFailDelayMS;                //!< Once there is a network failure, how long to wait for another attempt (in milliseconds, default 8 minutes)
    unsigned commFailureDelayMS;                //!< Once a communication failure or access denied occurs, how to long to wait for another attempt (in milliseconds, default 15 minutes)
    bool useRingIndicator;                      //!< Determines if use of ring indicator should be attempted when maxonTime=0
    string powerOnVerb;                         //!< The command to be executed to power the modem on (blank = no command)
    string powerOffVerb;                        //!< The command to be executed to power the modem off (blank = no command)
    unsigned modemOnDelayMS;			//!< A delay to add after turning on the modem (in milliseconds, default 25 seconds)
    unsigned networkTimeoutSeconds; 
    bool waitForNetworkRegistration;		//!< Determines if the modem should wait for network registration to be good before doing anything (95XX only)
};

}
}

BOOST_CLASS_VERSION(LiquidRobotics::SimpleSBDQueue::SSQCommunicatorSettings, 2)

#endif	/* __SSQCOMMUNICATORSETTINGS_H__ */

