/***************************************************************************
 *   Copyright (C) 2005 by Christof Donat   *
 *   cdonat@gmx.de   *
 *                                                                         *
 *   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 2 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, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/


#include <vector>
#include <string>
#include <map>
#include <boost/shared_ptr.hpp>
#include <boost/scoped_ptr.hpp>

#include "abstractcmdlineparser.h"
#include "configfile.h"

//! here comes the commandline-Parser - with help of the abstractcommandlineparser.

namespace commandline {

#ifndef HSADMIN_CMDLINEPARSER
#define HSADMIN_CMDLINEPARSER

using std::vector;
using std::string;
using std::map;
using boost::shared_ptr;
using boost::scoped_ptr;

// Parameter Objects are the resultof each Parser step and used in second step.

//! parsed values of a --setall, --set, --input, --passinput or a --infile option
class setParameter {
	public:
	string m_property;
	string m_value;

	string toXML(string &username, shared_ptr< ::ConfigFileParser > cfgfile);
};

//! parsed values of a --only or a --where option
class whereParameter {
	public:
	string m_property;
	string m_pattern;

	string toXML(string &username, shared_ptr< ::ConfigFileParser > cfgfile);
};

//! parsed values of a --global-order or a --order option
class orderParameter {
	public:
	string m_property;
	bool m_ascending;

	string toXML(string &username, shared_ptr< ::ConfigFileParser > cfgfile);
};

//! a whole parsed --call Option which holds all the relevant other options
class callParameter {
	public:
	callParameter(): m_module(""), m_function(""), m_display(""), m_ignoreerror(false), m_force(false), m_globalOrderIndex(-1) { };
	
	string m_module;
	string m_function;

	string m_display;
	vector<shared_ptr<setParameter> >   m_set;
	vector<shared_ptr<whereParameter> > m_where;
	vector<shared_ptr<orderParameter> > m_order;
	vector<string> m_objects;
	vector<string> m_unset;

	bool   m_ignoreerror;
	bool   m_force;
	int    m_globalOrderIndex;

	vector<string> parseDisplayspec();
	string evalDisplay(const map<string, string> &values);
	string toXML(string &username, shared_ptr< ::ConfigFileParser > cfgfile);
};

enum parseError { NOERROR = 0, NeedCall = 1 };

//! all the parsed values
class parsedParameters {
	public:
	parsedParameters();
	parseError m_error;
	string m_user;
	string m_ticket;
	string m_defaultDisplay;
	string m_addConfigFile;
	bool m_test;
	bool m_ignoreerrors;
	vector<shared_ptr<whereParameter> > m_only;
	vector<shared_ptr<setParameter> >   m_setall;
	vector<shared_ptr<orderParameter> > m_globalOrder;
	vector<shared_ptr<callParameter> >  m_call;
	vector<string> m_unsetall;

	string toXML(string &username, shared_ptr< ::ConfigFileParser > cfgfile);
};

// Option classes are used in first Parse step

//! --test
class TestOption: public abstractcommandlineparser::CmdLineOption<true,true,false,parsedParameters> {
	public:
	TestOption();
	protected:
	virtual bool handle(shared_ptr<parsedParameters> result);
};

//! --ignoreerror
class IgnoreErrorOption: public abstractcommandlineparser::CmdLineOption<true,true,false,parsedParameters> {
	public:
	IgnoreErrorOption();
	protected:
	virtual bool handle(shared_ptr<parsedParameters> result);
};

//! --ignoreerrors
class IgnoreErrorsOption: public IgnoreErrorOption {
	public:
	IgnoreErrorsOption();
	protected:
	virtual bool handle(shared_ptr<parsedParameters> result);
};

//! --verbosity
class VerbosityOption: public abstractcommandlineparser::CmdLineOption<true,true,true,parsedParameters> {
	public:
	VerbosityOption();
	bool parseThis(vector<string>& options, shared_ptr<parsedParameters> result);
	protected:
	virtual bool handle(string &parameter, shared_ptr<parsedParameters> result);
};

//! --quiet
class QuietOption: public abstractcommandlineparser::CmdLineOption<true,true,false,parsedParameters> {
	public:
	QuietOption();
	protected:
	virtual bool handle(string &parameter, shared_ptr<parsedParameters> result);
};

//! --runas
class RunAsOption: public abstractcommandlineparser::CmdLineOption<true,true,true,parsedParameters> {
	public:
	RunAsOption();
	protected:
	virtual bool handle(string &parameter, shared_ptr<parsedParameters> result);
};

//! --ticket
class TicketOption: public abstractcommandlineparser::CmdLineOption<true,true,true,parsedParameters> {
	public:
	TicketOption();
	protected:
	virtual bool handle(string &parameter, shared_ptr<parsedParameters> result);
};

//! --config
class ConfigOption: public abstractcommandlineparser::CmdLineOption<true,true,true,parsedParameters> {
	public:
	ConfigOption();
	protected:
	virtual bool handle(string & parameter, shared_ptr<parsedParameters> result);
};

//! --force
class ForceOption: public abstractcommandlineparser::CmdLineOption<true,false,false,parsedParameters> {
	public:
	ForceOption();
	protected:
	virtual bool handle(shared_ptr<parsedParameters> result);
};

//! --globals
class GlobalsOption: public abstractcommandlineparser::CmdLineOption<true,true,false,parsedParameters> {
	public:
	GlobalsOption();
	protected:
	virtual bool handle(shared_ptr<parsedParameters> result);
};

//! --where
class WhereOption: public abstractcommandlineparser::CmdLineOption<true,true,true,parsedParameters> {
	public:
	WhereOption();
	protected:
	virtual bool handle(string &parameter, shared_ptr<parsedParameters> result);
};

//! --only
class OnlyOption: public WhereOption {
	public:
	OnlyOption();
	protected:
	virtual bool handle(string &parameter, shared_ptr<parsedParameters> result);
};

//! --set
class SetOption: public abstractcommandlineparser::CmdLineOption<true,true,true,parsedParameters> {
	public:
	SetOption();
	protected:
	virtual bool handle(string &parameter, shared_ptr<parsedParameters> result);
};

//! --setall
class SetAllOption: public SetOption {
	public:
	SetAllOption();
	protected:
	virtual bool handle(string &parameter, shared_ptr<parsedParameters> result);
};

//! --infile
class InfileOption: public abstractcommandlineparser::CmdLineOption<true,true,true,parsedParameters> {
	public:
	InfileOption();
	protected:
	virtual bool handle(string &parameter, shared_ptr<parsedParameters> result);
};

//! --order
class OrderOption: public abstractcommandlineparser::CmdLineOption<true,true,true,parsedParameters> {
	public:
	OrderOption();
	protected:
	virtual bool handle(string &parameter, shared_ptr<parsedParameters> result);
};

//! --global-order
class GlobalOrderOption: public OrderOption {
	public:
	GlobalOrderOption();
	protected:
	virtual bool handle(string &parameter, shared_ptr<parsedParameters> result);
};

//! --input
class InputOption: public abstractcommandlineparser::CmdLineOption<true,true,true,parsedParameters> {
	public:
	InputOption();
	protected:
	virtual bool handle(string &parameter, shared_ptr<parsedParameters> result);
};

//! --passinput
class PassInputOption: public abstractcommandlineparser::CmdLineOption<true,true,true,parsedParameters> {
	public:
	PassInputOption();
	protected:
	virtual bool handle(string &parameter, shared_ptr<parsedParameters> result);
};

//! --display
class DisplayOption: public abstractcommandlineparser::CmdLineOption<true,true,true,parsedParameters> {
	public:
	DisplayOption();
	protected:
	virtual bool handle(string &parameter, shared_ptr<parsedParameters> result);
};

//! --default-display
class DefaultDisplayOption: public DisplayOption {
	public:
	DefaultDisplayOption();
	protected:
	virtual bool handle(string &parameter, shared_ptr<parsedParameters> result);
};

//! --call
class CallOption: public abstractcommandlineparser::CmdLineOption<true,true,true,parsedParameters> {
	public:
	CallOption();
	protected:
	virtual bool handle(string &parameter, shared_ptr<parsedParameters> result);
};

//! --unset
class UnsetOption: public abstractcommandlineparser::CmdLineOption<true,true,true,parsedParameters> {
	public:
	UnsetOption();
	protected:
	virtual bool handle(string &parameter, shared_ptr<parsedParameters> result);
};

//! --unsetall
class UnsetAllOption: public abstractcommandlineparser::CmdLineOption<true,true,true,parsedParameters> {
	public:
	UnsetAllOption();
	protected:
	virtual bool handle(string &parameter, shared_ptr<parsedParameters> result);
};

//! all other parameters are objectIDs.
class ObjectID: public abstractcommandlineparser::CmdLineOption<false,false,true,parsedParameters> {
	public:
	ObjectID();
	protected:
	virtual bool handle(string &parameter, shared_ptr<parsedParameters> result);
};

//! putting it all together in a typelist
typedef Parameterlist24(
	TestOption, 
	IgnoreErrorsOption, 
	VerbosityOption, 
	RunAsOption, 
	TicketOption,
	ConfigOption,
	SetAllOption, 
	UnsetAllOption,
	OnlyOption, 
	GlobalOrderOption, 
	DefaultDisplayOption, 
	IgnoreErrorOption, 
	ForceOption, 
	GlobalsOption, 
	WhereOption, 
	SetOption, 
	InfileOption, 
	OrderOption, 
	InputOption, 
	PassInputOption, 
	UnsetOption, 
	DisplayOption, 
	ObjectID, 
	CallOption ) allParameters;

//! generating a class with parse()-function from the list of Options
typedef abstractcommandlineparser::CmdLineOptionList<allParameters, parsedParameters> Parameters;

#else
class parsedParameters;
class setParameter;
class whereParameter;
class orderParameter;
class callParameter;
class TestOption;
class IgnoreErrorOption;
class IgnoreErrorsOption;
class VerbosityOption;
class RunAsOption;
class TicketOption;
class ConfigOption;
class SetAllOption;
class OnlyOption;
class UnsetAllOption;
class GlobalOrderOption;
class DefaultDisplayOption;
class ForceOption;
class GlobalsOption;
class WhereOption;
class SetOption;
class InfileOption;
class OrderOption;
class InputOption;
class PassInputOption;
class DisplayOption;
class unsetOption;
class CallOption;
class ObjectID;

#endif /* HSADMIN_CMDLINEPARSER */

};

