//-------------------------------------------------------------------------------------
// <copyright file="SensorControllerRunFileCmd.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 SensorControllerRunFileCmd template class, a template-
//	 based implementation of a command object that runs a file with one or
//	 more commands and executes those commands.
//
//	 The template parameters are:
//
//		- TControllerBase, the controller interface that is made available to all commands,
//		  usually abstract; this will be a base class for SensorController
//
//		- TCmdBase, the abstract base class that defines command operations
//
//		- TCmdID, the type if command ID that is used to track commands
//
//		- TExceptions, a class-based namespaces for exceptions that can be thrown
// </summary>
//
// <owner>Mike Cookson</owner>
//-------------------------------------------------------------------------------------

#ifndef __EventLib_SensorControllerRunFileCmd_h_
#define __EventLib_SensorControllerRunFileCmd_h_

#include "LqrSMACCmdLineParser.h"
#include "SensorControllerMultipleLinesCmd.h"
#include <boost/algorithm/string.hpp>

namespace LiquidRobotics {
namespace EventLib  {

template<class TControllerBase, class TCmdBase, class TCmdID, class TExceptions>
class SHARED_LIB_PUBLIC SensorControllerRunFileCmd : public SensorConcreteCommand<TControllerBase,TCmdBase,TCmdID,TExceptions>
{
public:

	typedef SensorConcreteCommand<TControllerBase,TCmdBase,TCmdID,TExceptions> Base;
	typedef LiquidRobotics::SMACFramework::CmdLineParser CmdLineParser;
	typedef typename Base::CmdBasePtr CmdPtr;
	typedef LiquidRobotics::SMACFramework::Logger Logger;
	typedef typename TControllerBase::ParsingContext ParsingContext;
	typedef std::string string;


	static CmdPtr Parse(const string& arg1, TControllerBase& ctrl, const CmdLineParser& parser, ParsingContext& context, Logger& logger)
	{
		return Parse(&arg1, 1, ctrl, parser, context, logger);
	}

	static CmdPtr Parse(const string& arg1, const string& arg2, TControllerBase& ctrl, const CmdLineParser& parser, ParsingContext& context, Logger& logger)
	{
		const string* args[] = { &arg1, &arg2 };
		return Parse(args, 2, ctrl, parser, context, logger);
	}

	static CmdPtr Parse(const string& arg1, const string& arg2, const string& arg3, TControllerBase& ctrl, const CmdLineParser& parser, ParsingContext& context, Logger& logger)
	{
		const string* args[] = { &arg1, &arg2, &arg3 };
		return Parse(args, 3, ctrl, parser, context, logger);
	}

	static CmdPtr Parse(const string** pMatch, const int matchLen, TControllerBase& ctrl, const CmdLineParser& parser, ParsingContext& context, Logger& logger)
	{
		using namespace std;
		typedef SensorControllerMultipleLinesCmd<TControllerBase,TCmdBase,TCmdID,TExceptions> MLines;

		const int numArgs = parser.Count();
		CmdPtr result;

		if (numArgs >= matchLen)
		{
			bool matching = true;

			for (int idx = 0; matching && (idx < matchLen); ++idx)
				if (!boost::iequals(*pMatch[idx], parser[idx]))
					matching = false;

			if (matching)
			{
				if (numArgs == matchLen)
				{
					stringstream msg;
					msg << "Missing file name parameter in '" << parser.GetOriginalCmdLine() << "'";
					throw invalid_argument(msg.str());
				}
				else if (numArgs == (matchLen+1))
				{
					const string& fileName = parser[matchLen];
					context.PushFileName(fileName);
					result = MLines::Parse(ctrl, fileName, context, logger);
					context.PopFileName(fileName);
				}
				else
				{
					stringstream msg;
					msg << "Too many parameters specified in '" << parser.GetOriginalCmdLine() << "'";
					throw invalid_argument(msg.str());
				}
			}
		}

		return result;
	}

};

}
}

#endif
