//	CmdLineParams.h - Class used to parse and handle command line parameters.
//  ----------------------------------------------------------------------------
//	This file is part of 'NiallsAVLib', base code for any kind of audiovisual
//	apps.
//	Copyright (C) 2012  Niall Moody
//	
//	This program is free software: you can redistribute it and/or modify
//	it under the terms of the GNU General Public License as published by
//	the Free Software Foundation, either version 3 of the License, or
//	(at your option) any later version.
//
//	This program is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//	GNU General Public License for more details.
//
//	You should have received a copy of the GNU General Public License
//	along with this program.  If not, see <http://www.gnu.org/licenses/>.
//	----------------------------------------------------------------------------

#ifndef CMDLINEPARAMS_H_
#define CMDLINEPARAMS_H_

#include <string>
#include <vector>

//------------------------------------------------------------------------------
///	Callback for when a parameter is found, so it can be handled correctly.
class CmdLineCallback
{
  public:
	///	Constructor.
	CmdLineCallback() {};
	///	Destructor.
	virtual ~CmdLineCallback() {};

	///	The callback itself.
	virtual void cmdLineParameterFound(const std::wstring& name,
									   const std::wstring& value) = 0;
};

//------------------------------------------------------------------------------
///	Class used to parse and handle command line parameters.
class CmdLineParams : public CmdLineCallback
{
  public:
	///	Constructor.
	CmdLineParams(const std::vector<std::wstring>& argv);
	///	Destructor.
	~CmdLineParams();

	///	Registers a callback to be associated with a parameter.
	/*!
		\param name The name of the parameter.
		\param longToken The long version of the parameter (e.g. --width).
		\param shortToken The short version of the parameter (e.g. -w).
		\param hasValue Whether or not the parameter has an associated value
		(e.g. -w 1024).
		\param defaultValue The default value this parameter should have. If
		it's a value-less parameter, leave this blank.
		\param callback The callback to be associated with this parameter.
	 */
	void registerCallback(const std::wstring& name,
						  const std::wstring& longToken,
						  const std::wstring& shortToken,
						  bool hasValue,
						  const std::wstring& defaultValue,
						  CmdLineCallback *callback);

	///	Used to display help text on the command line.
	void cmdLineParameterFound(const std::wstring& name,
							   const std::wstring& value);

	///	Goes through all the strings passed in in the constructor and calls any associated callbacks.
	/*!
		Make sure you register all your callbacks before you call this method.
	 */
	void handleParameters();

	///	Returns the number of registered parameters.
	int getNumRegisteredParams() const {return callbacks.size();};
	///	Returns the indexed registered parameter's name.
	const std::wstring& getRegisteredParam(int index) const {return callbacks[index].name;};
	///	Returns the indexed registered parameter's short token.
	const std::wstring& getRegisteredParamShort(int index) const {return callbacks[index].shortToken;};
	///	Returns whether or not the indexed registered parameter has a value.
	bool getRegisteredParamHasValue(int index) const {return callbacks[index].hasValue;};

	///	Returns the raw command line arguments.
	const std::vector<std::wstring>& getArguments() const {return arguments;};
  private:
	///	Struct representing a parameter-callback pair.
	struct ParameterCallback
	{
		///	The parameter's name (how it will be referred to by its callback).
		std::wstring name;
		///	The long version of the parameter on the command line (e.g. --width).
		std::wstring longToken;
		///	The short version of the parameter on the command line (e.g. -w).
		std::wstring shortToken;
		///	Whether or not the parameter has an associated value (e.g. -w 1024).
		bool hasValue;
		///	The default value of the parameter.
		std::wstring defaultValue;
		///	The associated callback.
		CmdLineCallback *callback;
	};

	///	The command line arguments as initially passed in.
	std::vector<std::wstring> arguments;
	///	All the registered callbacks.
	std::vector<ParameterCallback> callbacks;
};

#endif
