/***************************************************************************
                Parameter
                -----------------------------------------
	begin      : 2015/05/13
	copyright  : (C) 2011 SolutionBox Inc.
	author     : Service 1 Team
	email      : svc1@solbox.com
	version    : 3.1.0

    CopyRight(C) 2011 SolutionBox Inc. All Rights reserved.
    Redistribution and use in source and binary forms, with or with out
    modification, are not permitted in outside of SolutionBox Inc.
***************************************************************************/
#include "rc_cmove.h"
#include "parameter.h"
#include "Config.h"

#define REPORT_NAME		"report"
#define MAX_DB_POOL		10
#define DEFAULT_FHS_MOUNT "/stg/node0,/stg/node1,/stg/node2"

parameter *parameter::inst = NULL;

parameter::parameter()
	:m_confpath(DEFAULT_CONFIG_FILE), m_networkmode(1), m_includedel(false)
{
}

parameter::~parameter()
{
}

parameter* parameter::getInstance()
{
	if( parameter::inst == NULL )
	{
		parameter::inst = new parameter;
	}

	return parameter::inst;
}

void parameter::release()
{
	if( parameter::inst != NULL )
	{
		delete parameter::inst;
		parameter::inst = NULL;
	}
}

void parameter::printusage()
{
	cerr << "usage: " << PROG_NAME << " [-v] [-m mode] ([-f path] [-t path] ";
	cerr << "([-n mode])) ([-p starttime:endtime] [-d] [-s service sequence])";
	cerr << endl;
}

bool parameter::argvtoparam( int argc, char * const argv[] )
{
	int	o;

	if( argc == 1 )
	{
		cerr << "Invalid input arguments." << endl;
		return false;
	}

	while ((o = getopt(argc, argv, "vf:n:t:c:m:p:s:d")) >= 0)
	{
		switch (o)
		{
		case 'v': // version info
			cerr << "[info] " << PROG_NAME << " Version : " << PROG_VERSION << endl;
			exit(EXIT_SUCCESS);
			break;
		// use common
		case  'm':// mode
			m_mode = optarg;
			break;
		case 'c': // config path
			m_confpath = optarg;
			break;	
		// use move & use copy
		case 'f': // transfer list path
			{
				if (issyncmode())
				{
					cerr << "'-f' Available copy or move mode.";
					cerr << endl;
					return false;
				}

				m_synclistpath = optarg;
			}
			break;
		case 't': // host list path
			{
				if (issyncmode())
				{
					cerr << "'-t' Available copy or move mode.";
					cerr << endl;
					return false;
				}
				m_targetlistpath = optarg;
			}			
			break;
		// use move
		case 'n': // network mode
			{
				if (ismovemode() == false)
				{
					cerr << "'-n' Available only move mode.";
					cerr << endl;
					return false;
				}

				m_networkmode = atoi(optarg);
			}			
			break;
		//use sync
		case 'p':
			{
				if (issyncmode() == false)
				{
					cerr << "'-p' Available only sync mode.";
					cerr << endl;
					return false;
				}

				string t = optarg;
				StringSplit(t, ":", m_synctime);

				if (m_synctime.size() != 2)
				{
					cerr << "The request does not fit the format. [-p starttime:endtime]";
					cerr << endl;
					return false;
				}
			}
			break;
		case 's':
			{
				if (issyncmode() == false)
				{
					cerr << "'-s' Available only sync mode.";
					cerr << endl;
					return false;
				}

				m_service = optarg;
			}			
			break;
		case 'd':
			{
				if (issyncmode() == false)
				{
					cerr << "'-d' Available only sync mode.";
					cerr << endl;
					return false;
				}
				m_includedel = true;
			}			
			break;
		default: // unknown
#ifdef _DEBUG
			cout << "unknown arguments." << endl;
#endif // _DEBUG
			printusage();
			return false;
			break;
		}
	}

	if (m_mode.empty())
	{
		printusage();
		return false;
	}

	return true;
}

bool parameter::loadconf()
{
#ifdef _DEBUG
	cout << "conf :" << m_confpath << endl;
#endif // _DEBUG
	Config conf;

	// Config File open
	if( conf.Open(m_confpath) == false )
	{
		return false;
	}

	string szValue;

	// log path
	if( getconfdata( conf, "DEFAULT_LOG_DIR" ,szValue, true ) == false )
		return false;
	m_logpath = szValue;
	m_logreport = m_logpath + "/" + REPORT_NAME;

	// log level
	if( getconfdata( conf, "LOG_LEVEL" ,szValue, true ) == false )
		return false;
	m_loglevel = atoi(szValue.c_str());

	// work pool
	if( getconfdata( conf, "WORK_POOL" ,szValue, false ) == false )
		return false;
	m_workpoolcnt = atoi(szValue.c_str());

	// skip keyword
	getconfdata(conf, "SKIP_KEYWORD", m_skipkey, true, false);
	//if( getconfdata(conf, "SKIP_KEYWORD", m_skipkey, false)  == false )
	//	return false;

	databaseinfo m;
	// RCDB Information
	//  master
	if( getconfdbinof(conf, parameter::MASTER, m) == false )
		return false;

	m_dbinfo.push_back(m);

	// DB Connection pool 
	int pool = 0;
	getconfdata(conf, "DB_POOL", szValue, false);
	pool = atoi(szValue.c_str());
	m_dbpoolcnt.push_back(pool);


	if( 1 > m_dbpoolcnt[0] || m_dbpoolcnt[0] > MAX_DB_POOL )
		m_dbpoolcnt[0] = 4;

	// FHS_STORAGE_MOUNT
	if (getconfdata(conf, "FHS_STORAGE_MOUNT", m_fhsmount, true, false) == false)
	{
		StringSplit(DEFAULT_FHS_MOUNT, ",", m_fhsmount);
	}

	return true;
}

bool parameter::getconfdbinof(Config &conf,int dbinfotype, databaseinfo &data)
{
	bool bcommon = true;
	string szValue, szkey, szextkey;
		
	switch(dbinfotype)
	{
	case parameter::MASTER:
		szextkey = "";
		bcommon = true;
		break;
	case parameter::SLAVE_FIRST:
		szextkey = "_SLAVE_FIRST";
		bcommon = false;
		break;
	case parameter::SLAVE_SECOND:
		szextkey = "_SLAVE_SECOND";
		bcommon = false;
		break;
	default:
		return false;
		break;
	}

	// db host
	szValue.clear();
	szkey = "RCDB_IP"+ szextkey;
	if( getconfdata( conf, szkey, szValue, bcommon) == false )
	{
		return false;
	}
	data.m_hostaddr = szValue;

	// db port
	szValue.clear();
	szkey = "RCDB_PORT"+ szextkey;
	if( getconfdata( conf, szkey, szValue, bcommon) == false )
	{
		return false;
	}
	data.m_port = atoi(szValue.c_str());

	// db database name
	szValue.clear();
	szkey = "RCDB_DB_NAME"+ szextkey;
	if( getconfdata( conf, szkey, szValue, bcommon) == false )
	{
		return false;
	}
	data.m_dbname = szValue;

	// db user
	szValue.clear();
	szkey = "RCDB_ACCT"+ szextkey;
	if( getconfdata( conf, szkey, szValue, bcommon) == false )
	{
		return false;
	}
	data.m_user = szValue;

	// db password
	szValue.clear();
	szkey = "RCDB_ACCT_PW"+ szextkey;
	if( getconfdata( conf, szkey, szValue, bcommon) == false )
	{
		return false;
	}
	data.m_pw = szValue;
	return true;
}

bool parameter::getconfdata(Config &conf, const string& key, string& value, bool bcommon /* = false */, bool returnerr /*= true*/)
{
	value.clear();
	string prefix = "[error]";
	
	if (returnerr == false)
		prefix = "[warning]";

	if( conf.GetConfig( PROG_NAME, key, value ) == false )
	{
		if(bcommon == false)
		{			
			cerr << prefix << " Config info get failed. [" << PROG_NAME << "]->" << key << endl;
			return false;
		}
		else
		{
			if( conf.GetConfig( "COMMON", key, value ) == false )
			{
				cerr << prefix << " Config info get failed. [COMMON]->" << key << endl;
				return false;
			}
		}
	}

	return true;
}

bool parameter::getconfdata(Config &conf, const string& key, vector< string >& value, bool bcommon /*= false */, bool returnerr /*= true*/)
{
	value.clear();
	
	string prefix = "[error]";
	if (returnerr == false)
		prefix = "[warning]";

	if( conf.GetConfig( PROG_NAME, key, value ) == false )
	{
		if(bcommon == false)
		{
			cerr << prefix << " Config info get failed. [" << PROG_NAME << "]->" << key << endl;
			return false;
		}
		else
		{
			if( conf.GetConfig( "COMMON", key, value ) == false )
			{
				cerr << prefix << " Config info get failed. [COMMON]->" << key << endl;
				return false;
			}
		}
	}

	return true;
}

void parameter::print_loginfo()
{
	cout << "Log Path	:	" << m_logpath << "/"<< PROG_NAME << "/" << endl;
	cout << "Log Level	:	" << m_loglevel <<endl;
}

void parameter::print_dbinfo()
{	
	databaseinfo m = getdbinfo(parameter::MASTER);
	cout << "Master DB	:	" << m.m_hostaddr << "," <<  m.m_port << "," << 
		m.m_dbname << "," << m.m_user << "," << m.m_pw <<endl ;
}
