/***************************************************************************
 *   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.             *
 ***************************************************************************/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <iostream>
#include <cstdlib>
#include <string>
#include <vector>

#include <boost/shared_ptr.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/algorithm/string.hpp>

#include "cmdlineparser.h"
#include "configfile.h"
#include "logger.h"
#include "transaction.h"

using std::string;
using std::vector;
using std::cerr;
using std::endl;
using boost::shared_ptr;
using boost::scoped_ptr;
using boost::starts_with;

void printErrorMessage(Transaction& transact, vector<string>& options) {
	shared_ptr<commandline::parsedParameters> p = transact.getParsed();
	string FailedOption = options[0];
	if( starts_with(FailedOption,"--") )
		FailedOption = FailedOption.substr(2);
	else if( starts_with(FailedOption,"-") )
		FailedOption = FailedOption.substr(1,2);

	cerr << "Error on Commandline at Parameter '"<< FailedOption;
	if( p->m_error == commandline::NeedCall )
		cerr << ": call specific Parameter before call";
	cerr << endl;
}

void printUsage(char* cmdname) {
	cerr << "Usage: " << endl << endl;
	cerr << cmdname << " [--test|-t]" << endl;
	cerr << "[--ignoreerrors|-e]" << endl;
	cerr << "[--verbosity=<level>|-v <level>]" << endl;
	cerr << "[--quiet|-q]" << endl;
	cerr << "[--runas=<user>|-r <user>]" << endl;
	cerr << "[--ticket=<ticketfile>|-T <ticketfile>]" << endl;
	cerr << "[--config=<configfile>|-C <configfile>]" << endl;
	cerr << "[--default-display:<displaySpec>|-D <displaySpec>]" << endl;
	cerr << "[(--only:<property_1>=<expr_1>|-W <property_1>=<expr_1>)" << endl;
	cerr << " ... (--only:<property_n>=<expr_n>|-W <property_n>=<expr_n>)]" << endl;
	cerr << "[(--setall:<property_1>=<value_1>|-S <property_1>=<value_1>)" << endl;
	cerr << " ... (--setall:<property_n>=<value_n>|-S <property_n>=<value_n>)]" << endl;
	cerr << " [(--unsetall:property_1|-U property_1) ... (--unsetall:property_n|-U property_n)]" << endl;
	cerr << "[(--global-order:<property_1>[=(asc|desc|a|d)]|-O <property_1>[=(asc|desc|a|d)])" << endl;
	cerr << "    ..." << endl;
	cerr << " (--global-order:<property_n>[=(asc|desc|a|d)]|-O <property_n>[=(asc|desc|a|d)]]" << endl;
	cerr << " [--ignoreerrors|-E]" << endl;
	cerr << "(--call:<module_1>.<function_1>|-c <module_1>.<function_1>)" << endl;
	cerr << "  [--force]" << endl;
	cerr << "  [--ignoreerror|-e]" << endl;
	cerr << "  [--display:<displaySpec>|-d <displaySpec>]" << endl;
	cerr << "  [(--where:<property_1_1>=<expr_1_1>|-w <property_1_1>=<expr_1_1>)" << endl;
	cerr << "   ... (--where:<property_1_n>=<expr_1_n>|-w <property_1_n>=<expr_1_n>)]" << endl;
	cerr << "  [(--set:<property_1_1>=<value_1_1>|-s <property_1_1>=<value_1_1>)" << endl;
	cerr << "   ... (--set:<property_1_n>=<value_1_n>|-s <property_1_n>=<value_1_n>)]" << endl;
	cerr << "  [(--input:<property_1_1>|-i <property_1_1>)" << endl;
	cerr << "   ... (--input:<property_1_n>|-i <property_1_n>)]" << endl;
	cerr << "  [(--passinput:<property_1_1>|-p <property_1_1>)" << endl;
	cerr << "   ... (--passinput:<property_1_n>|-p <property_1_n>)]" << endl;
	cerr << "  [(--infile:<property_1_1>=<file_1_1>|-f <property_1_1>=<file_1_1>)" << endl;
	cerr << "    ... (--infile:<property_1_n>=<file_1_n>|-f <property_1_n>=<file_1_n>)]" << endl;
	cerr << "     [(--unset:property_1_1|-u property_1_1]) ... (--unset:property_1_n|-u property_1_n])]" << endl;
	cerr << "  [(--order:<property_1_1>[=(asc|desc|a|d)]|-o <property_1_1>[=(asc|desc|a|d)])" << endl;
	cerr << "      ..." << endl;
	cerr << "      [--globals|-l]" << endl;
	cerr << "      ..." << endl;
	cerr << "   (--order:<property_1_n>[=(asc|desc|a|d)]|-o <property_1_n>[=(asc|desc|a|d)]]" << endl;
	cerr << "  [object_1_1 ... object_1_n]" << endl;
	cerr << "..." << endl;
	cerr << "(--call:<module_m>.<function_m>|-c <module_m>.<function_m>)" << endl;
	cerr << "  [--force]" << endl;
	cerr << "  [--ignoreerror|-e]" << endl;
	cerr << "  [--display:<displaySpec>|-d <displaySpec>]" << endl;
	cerr << "  [(--where:<property_m_1>=<expr_m_1>|-w <property_m_1>=<expr_m_1>)" << endl;
	cerr << "   ... (--where:<property_m_n>=<expr_m_n>|-w <property_m_n>=<expr_m_n>)]" << endl;
	cerr << "  [(--set:<property_m_1>=<value_m_1>|-s <property_m_1>=<value_m_1>)" << endl;
	cerr << "   ... (--set:<property_m_n>=<value_m_n>|-s <property_m_n>=<value_m_n>)]" << endl;
	cerr << "  [(--input:<property_m_1>|-i <property_m_1>)" << endl;
	cerr << "   ... (--input:<property_m_n>|-i <property_m_n>)]" << endl;
	cerr << "  [(--passinput:<property_m_1>|-p <property_m_1>)" << endl;
	cerr << "   ... (--passinput:<property_m_n>|-p <property_m_n>)]" << endl;
	cerr << "  [(--infile:<property_m_1>=<file_m_1>|-f <property_m_1>=<file_m_1>)" << endl;
	cerr << "   ... (--infile:<property_m_n>=<file_m_n>|-f <property_m_n>=<file_m_n>)]" << endl;
	cerr << "     [(--unset:property_m_1|-u property_m_1]) ... (--unset:property_m_n|-u property_m_n])]" << endl;
	cerr << "  [(--order:<property_m_1>[=(asc|desc|a|d)]|-o <property_m_1>[=(asc|desc|a|d)])" << endl;
	cerr << "      ..." << endl;
	cerr << "      [--globals|-l]" << endl;
	cerr << "      ..." << endl;
	cerr << "   (--order:<property_m_n>[=(asc|desc|a|d)]|-o <property_m_n>[=(asc|desc|a|d)]]" << endl;
	cerr << "  [object_m_1 ... object_m_n]" << endl;
}

int main(int argc, char *argv[])
{
	if( argc == 1 ) {
		printUsage(*argv);
		exit(1);
	}
	vector<string> options(argv+1,argv+argc);
	Transaction transact(options);
	
	if( !transact ) {
		printErrorMessage(transact, options);
		printUsage(*argv);
		exit(1);
	}

	Logger::log(Logger::DEBUG,"have parsed Parameters");
	
	scoped_ptr<ConfigFileFinder> cfff(new ConfigFileFinder(transact));
	shared_ptr<ConfigFileParser> cfg(new ConfigFileParser(cfff.get()));

	Logger::log(Logger::DEBUG,"have read config File");

	transact(cfg);

	Logger::log(Logger::DEBUG,"have executed Transaction");

	//cout << transact.formatOutput();
	//exit(transact.errorCode());

	return 0;
}
