//-------------------------------------------------------------------------------------------------
// <copyright file="SBGPCTDPowerCmd.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>
// 	Declaration of SBGPCTDPowerCmd, which implements the power on/off command for SBGPCTDController
// </summary>
//
// <owner>Mike Cookson</owner>
//-------------------------------------------------------------------------------------------------

#ifndef SBGPCTDPOWERCMD_H_
#define SBGPCTDPOWERCMD_H_

#include "SBGPCTDClassConfig.h"
#include "LqrSMACBooleanParser.h"
#include "LqrSMACCmdLineParser.h"

namespace LiquidRobotics {
namespace SeabirdGPCTD {

/*! \class SBGPCTDPowerCmd
 *  \brief Implementation of the Seabird GPCTD interface Power command
 *  \sa SBGPCTDController, SBGPCTDController::ParseCommand(), SBGPCTDController::SetPower()
 *
 *  The Power command allows the user to turn power on or off to the sensor.
 *  The operation is delegated to the Controller's SetPower() method.
 *
 *  Command classes always implement a Parse member function that determines if
 *  parameters supplied indicate the command implemented by the class and parses
 *  out the the parameters.  If successful, the parameters are used to
 *  instantiate the class.  The class derives from the "concrete command" class,
 *  which provides members and data related used by all commands.
 */
class SHARED_LIB_PUBLIC SBGPCTDPowerCmd : public SBGPCTDConcreteCmd
{
public:

	//! Define a short-cut for CmdBasePtr (don't want "using namespace" in header files)
	typedef SBGPCTDConcreteCmd::CmdBasePtr CmdPtr;

	//! Define a short-cut for SMACFramework's CmdLineParser (don't want "using namespace" in header files)
	typedef LiquidRobotics::SMACFramework::CmdLineParser CmdLineParser;

	//! Define a short-cut for SMACFramework's Logger (don't want "using namespace" in header files)
	typedef LiquidRobotics::SMACFramework::Logger Logger;

	//! Define a short-cut for ParsingCOntext (don't want "using namespace" in header files)
	typedef SBGPCTDControllerBase0::ParsingContext ParsingContext;

	/*! \brief Class constructor
	 */
	SBGPCTDPowerCmd(
			TCon& _ctrl,			/**< [in] References the Controller class, used during execution */
			const string& _cmd,		/**< [in] A copy of the original command line */
			bool _power,			/**< [in] true if powering the sensor on, false if powering it off */
			Logger& _logger
			)
	: SBGPCTDConcreteCmd(_ctrl)
	, ctrl(_ctrl)
	, cmd(_cmd)
	, power(_power)
	, logger(_logger)
	{
	}

	/*! \brief Class destructor
	 */
	virtual ~SBGPCTDPowerCmd()
	{
	}

	/*! \brief Implementation of command execution.
	 *
	 * (Overrides the base class member)
	 */
	virtual void Execute()
	{
		using namespace std;
		using namespace LiquidRobotics::SMACFramework;

		try
		{
			SignalStarted();

			ctrl.SetPower(power);

			CmdOutputFormatter::Ptr fmt = GetOutputFormatter();
			if (fmt)
					fmt->AppendOutput(string("OK"));
		}
		catch(exception& ex)
		{
			stringstream msg;
			msg << "ERROR: " << ex.what();

			CmdOutputFormatter::Ptr fmt = GetOutputFormatter();
			if (fmt)
					fmt->AppendOutput(msg.str());
		}
	}

	/*! \brief Parses command parameters and creates command instance
	 *  \returns A smart pointer to an instance of the command class or a nil smart pointer
	 *
	 * If the first parameter to the command matches arg1 and the second parameter matches arg2,
	 * the Parse member uses the remaining parameters configure a new instance of this command
	 * class and returns it as a smart pointer; exceptions may be thrown if parameters are not
	 * valid.
	 *
	 * If the command doesn't match the arguments, then a nil smart pointer is returned.
	 */
	static CmdPtr Parse(
			const string& arg1,					/**< [in] Required value for parameter #1 to the command */
			const string& arg2,					/**< [in] Required value for parameter #2 to the command */
			TCon& ctrl,							/**< [in] Reference to the controller (retained for command execution */
			const CmdLineParser& parser,		/**< [in] Reference to a parsed input command line used to get access to command parameters */
			ParsingContext& context,			/**< [in] Information about the remote caller (not used by the parser) */
			Logger& logger						/**< [in] Logger to be used while parsing or executing the command */
			)
	{
		using namespace std;
		using namespace LiquidRobotics::SMACFramework;

		CmdPtr result;
		const CmdLineParser::StringArray& tokens = parser.GetTokens();

		if ((tokens.size() >= 2)
		 && boost::iequals(tokens[0], arg1)
		 && boost::iequals(tokens[1], arg2))
		{
			if (tokens.size() < 3)
				throw invalid_argument("Not enough arguments");

			if (tokens.size() > 3)
				throw invalid_argument("Too many arguments");

			result.reset(new SBGPCTDPowerCmd(ctrl, parser.GetOriginalCmdLine(), StringToBoolean(tokens[2]), logger));
		}

		return result;
	}

private:

	SBGPCTDControllerBase0& ctrl;			//!< Reference to the controller
	const string cmd;						//!< Copy of the command that was issued by the user
	const bool power;						//!< true if powering on, false if powering off
	Logger& logger;							//!< Reference to the logger to be used while running
};

}
}

#endif /* SBGPCTDPOWERCMD_H_ */
