/***************************************************************************
                   Config Class (Config.cpp)
                -----------------------------------------

	begin      : 2013/02/13
	copyright  : (C) 2013 Solbox Inc.
	author     : Development 1 Team
					- 2013/02/14 - 1st dadamin
	email      : dev1@solbox.com
	version    : 3.2.0

	CopyRight(C) 2005 Solbox Inc. All Rights reserved.
	Redistribution and use in source and binary forms, with or with out
	modification, are not permitted in outside of Solbox Inc.
***************************************************************************/
#include "rc_mngd.h"
#include "Configs.h"
#include "Config.h"
#include "Service.h"

#define		DBPOOL_CNT			2
CMyConfig *CMyConfig::m_pInstance = NULL;

CCommonConfig::CCommonConfig( string szFilename, string szProgramName )
	: m_szConfigFile(szFilename), m_szProgramName(szProgramName), 
	m_DBPoolCnt(DBPOOL_CNT),
	m_nLogLevel(0)
{
}

CCommonConfig::~CCommonConfig()
{
}

bool CCommonConfig::LoadConf()
{
#ifdef _DEBUG
	cout << "CCommonConfig::LoadConf() =>" << endl;
#endif // _DEBUG
	string szValue;

	// Config 처리를 위한 객체 생성
	Config conf;

	// Config File open
	if( conf.Open( m_szConfigFile ) == false )
	{
		m_szErrMessage = "Config file open failed.[" + m_szConfigFile + "]";
		return false;
	}

	// log path
	if( conf.GetConfig( "COMMON", "DEFAULT_LOG_DIR", szValue ) )
	{
		m_szAppLogRoot = szValue;
	}

	// log level
	if( conf.GetConfig( "COMMON", "LOG_LEVEL", szValue ) )
	{
		m_nLogLevel = atoi( szValue.c_str() );
	}

	// RC ID
	if( conf.GetConfig( "COMMON", "RC_ID", szValue ) )
	{
		m_szRcid = szValue;
	}

	// RCDB Access Information
	if( conf.GetConfig( "COMMON", "RCDB_IP", szValue ) )
	{
		m_cDatabaseInfo.m_szRcdbIp = szValue;
	}
	if( conf.GetConfig( "COMMON", "RCDB_PORT", szValue ) )
	{
		m_cDatabaseInfo.m_nRcdbPort = atoi( szValue.c_str() );
	}
	if( conf.GetConfig( "COMMON", "RCDB_DB_NAME", szValue ) )
	{
		m_cDatabaseInfo.m_szRcdbName = szValue;
	}
	if( conf.GetConfig( "COMMON", "RCDB_ACCT", szValue ) )
	{
		m_cDatabaseInfo.m_szRcdbAcct = szValue;
	}
	if( conf.GetConfig( "COMMON", "RCDB_ACCT_PW", szValue ) )
	{
		m_cDatabaseInfo.m_szRcdbAcctPw = szValue;
	}

#ifdef _DEBUG
	PrintValue();
#endif // _DEBUG

	return true;
}

bool CCommonConfig::CheckValue()
{
	if(m_szAppLogRoot.empty())
	{
		m_szErrMessage  = "Config info get failed. [" + m_szProgramName + " or COMMON]->DEFAULT_LOG_DIR";
		return false;
	}

	if( m_nLogLevel <= 0)
	{
		m_szErrMessage  = "Config info get failed. [" + m_szProgramName + " or COMMON]->LOG_LEVEL";
		return false;
	}

	if(m_szRcid.empty())
	{
		m_szErrMessage  = "Config info get failed. [" + m_szProgramName + " or COMMON]->RC_ID";
		return false;
	}

	if(m_cDatabaseInfo.m_szRcdbIp.empty())
	{
		m_szErrMessage  = "Config info get failed. [" + m_szProgramName + " or COMMON]->RCDB_IP";
		return false;
	}

	if( m_cDatabaseInfo.m_nRcdbPort <= 0)
	{
		m_szErrMessage  = "Config info get failed. [" + m_szProgramName + " or COMMON]->RCDB_PORT";
		return false;
	}

	if(m_cDatabaseInfo.m_szRcdbName.empty())
	{
		m_szErrMessage  = "Config info get failed. [" + m_szProgramName + " or COMMON]->RCDB_DB_NAME";
		return false;
	}

	if(m_cDatabaseInfo.m_szRcdbAcct.empty())
	{
		m_szErrMessage  = "Config info get failed. [" + m_szProgramName + " or COMMON]->RCDB_ACCT";
		return false;
	}

	if(m_cDatabaseInfo.m_szRcdbAcctPw.empty())
	{
		m_szErrMessage  = "Config info get failed. [" + m_szProgramName + " or COMMON]->RCDB_ACCT_PW";
		return false;
	}

	return true;	
}

void CCommonConfig::PrintValue()
{
	cout << "Log   Value : " << m_szAppLogRoot << "," << m_nLogLevel << endl;
	cout << "RC    Value : " << m_szRcid << endl;
	cout << "RCDB  Value : " << m_cDatabaseInfo.m_szRcdbIp << "," 
		<< m_cDatabaseInfo.m_nRcdbPort << "," << m_cDatabaseInfo.m_szRcdbName 
		<< "," << m_cDatabaseInfo.m_szRcdbAcct << "," << m_cDatabaseInfo.m_szRcdbAcctPw << endl;
}

CMyConfig::CMyConfig( string szFilename, string szProgramName)
	: CCommonConfig(szFilename, szProgramName), m_nFHSCtlTCP(0)
{
}

CMyConfig::~CMyConfig()
{
	m_ServiceList.clear();
}

static void StringSplit(string str, string delim, vector<string> &results, bool bUseEmpty /*= false*/)
{
	const string strEmpty("");
	string::size_type cutAt;

	while( (cutAt = str.find_first_of(delim)) != str.npos )
	{
		if(cutAt > 0)
		{
			results.push_back(str.substr(0,cutAt));
		}
		else
		{
			if(bUseEmpty && cutAt == 0)
				results.push_back(strEmpty);
		}
		str = str.substr(cutAt+1);
	}
	if(str.length() > 0)
	{
		results.push_back(str);
	}
}

bool CMyConfig::LoadConf()
{
	CCommonConfig::LoadConf();
#ifdef _DEBUG
	cout << "CMyConfig::LoadConf() =>" << endl;
#endif // _DEBUG
	string szValue;

	// Config 처리를 위한 객체 생성
	Config conf;

	// Config File open
	if( conf.Open( m_szConfigFile ) == false )
	{
		m_szErrMessage = "Config file open failed.[" + m_szConfigFile + "]";
		return false;
	}

	// Config File open
	if( conf.GetConfig( m_szProgramName, "DEFAULT_LOG_DIR", szValue ) )
	{
		m_szAppLogRoot = szValue;
	}

	// log level
	if( conf.GetConfig( m_szProgramName, "LOG_LEVEL", szValue ) )
	{
		m_nLogLevel = atoi( szValue.c_str() );
	}

	// RC ID
	if( conf.GetConfig( m_szProgramName, "RC_ID", szValue ) )
	{
		m_szRcid = szValue;
	}

	// RCDB Access Information
	if( conf.GetConfig( m_szProgramName, "RCDB_IP", szValue ) )
	{
		m_cDatabaseInfo.m_szRcdbIp = szValue;
	}
	if( conf.GetConfig( m_szProgramName, "RCDB_PORT", szValue ) )
	{
		m_cDatabaseInfo.m_nRcdbPort = atoi(szValue.c_str()  );
	}
	if( conf.GetConfig( m_szProgramName, "RCDB_DB_NAME", szValue ) )
	{
		m_cDatabaseInfo.m_szRcdbName = szValue;
	}
	if( conf.GetConfig( m_szProgramName, "RCDB_ACCT", szValue ) )
	{
		m_cDatabaseInfo.m_szRcdbAcct = szValue;
	}
	if( conf.GetConfig( m_szProgramName, "RCDB_ACCT_PW", szValue ) )
	{
		m_cDatabaseInfo.m_szRcdbAcctPw = szValue;
	}
	
	// Database Connection Poo
	if (conf.GetConfig(m_szProgramName, "DB_POOL", szValue))
	{
		m_DBPoolCnt = atoi(szValue.c_str());
	}

	// FHS Control Port - TCP
	if( conf.GetConfig( m_szProgramName, "FHS_CONTROL_TCP_PORT", szValue ) )
	{
		m_nFHSCtlTCP = atoi( szValue.c_str() );
	}

	// RC Domain name 
	if( conf.GetConfig( m_szProgramName, "RC_DOMAIN_NAME", szValue ) )
	{
		m_szRCDomain = szValue;
	}

	// SSL 인증서/ 개인키 파일
	if( conf.GetConfig( m_szProgramName, "SSL_CERTIFICATE_FILE", szValue ) )
	{
		m_szCertFile = szValue;
	}

	if( conf.GetConfig( m_szProgramName, "SSL_PRIVATEKEY_FILE", szValue ) )
	{
		m_szPrivateFile = szValue;
	}
	
	// RC Management Service List
	string k = "=";
	conf.SetDelimiter(k, "|");
	vector< string >  vec;
	if(conf.GetConfig(m_szProgramName, "SERVICE_LIST", vec))
	{
		for (vector<string>::iterator it = vec.begin() ; it != vec.end(); ++it)
		{
#ifdef _DEBUG
			cout << ' ' << *it << endl;
#endif //_DEBUG
			vector< string >  vec2;
			StringSplit(*it, ",", vec2, true);
			if(!vec2.empty())
			{
				CServiceInfo info;
				info.m_port = atoi(vec2[0].c_str());

				if (vec2[1].find("XML") != string::npos)
					info.m_type = CServiceInfo::XML;
				else if (vec2[1].find("SDK") != string::npos)
					info.m_type = CServiceInfo::SDK; 
				else if (vec2[1].find("ETC") != string::npos)
					info.m_type = CServiceInfo::ETC;
				else if (vec2[1].find("STR") != string::npos)
					info.m_type = CServiceInfo::STR;
				else {
					//nothing
				}

				info.m_enableSSL = (vec2[2].compare("Y") == 0);

				if(info.m_type != CServiceInfo::UNSET)
					m_ServiceList.push_back(info);
			}			
		}
	}

#ifdef _DEBUG
	PrintValue();
#endif // _DEBUG
	return true;
}

bool CMyConfig::CheckValue()
{
	if( CCommonConfig::CheckValue() )
	{
		if( m_nFHSCtlTCP <= 0)
		{
			m_szErrMessage  = "Config info get failed. [" + m_szProgramName + "]->FHS_CONTROL_TCP_PORT";
			return false;
		}

		if( m_szRCDomain.empty() )
		{
			m_szErrMessage  = "Config info get failed. [" + m_szProgramName + "]->RC_DOMAIN_NAME";
			return false;
		}

		if( m_ServiceList.empty())
		{
			m_szErrMessage  = "Config info get failed. [" + m_szProgramName + "]->SERVICE_LIST";
			return false;
		}

		if( m_szCertFile.empty())
		{
			m_szErrMessage  = "Config info get failed. [" + m_szProgramName + "]->SSL_CERTIFICATE_FILE";
			return false;
		}

		if( m_szPrivateFile.empty())
		{
			m_szErrMessage  = "Config info get failed. [" + m_szProgramName + "]->SSL_PRIVATEKEY_FILE";
			return false;
		}
	}

	return true;
}

void CMyConfig::PrintValue()
{
	CCommonConfig::PrintValue();
	
	cout << "SSL Key file :" << m_szCertFile << "," << m_szPrivateFile << endl;
	cout << "FHSCTL  Value : " << m_nFHSCtlTCP << endl;
	cout << "RC Domain : " << m_szRCDomain << endl;

	cout << "Service info => " << endl;
	for (list<CServiceInfo>::iterator it= m_ServiceList.begin(); it != m_ServiceList.end(); ++it)
	{
		(*it).PrintInfo();
	}
}

bool CMyConfig::Init( string szProgramName, string szFilename )
{
	if( CMyConfig::m_pInstance == NULL )
	{
		CMyConfig::m_pInstance = new CMyConfig(szFilename, szProgramName);
	}

	return true;
}

void CMyConfig::Exit()
{
	if( CMyConfig::m_pInstance != NULL )
	{
		delete CMyConfig::m_pInstance;
		CMyConfig::m_pInstance = NULL;
	}
}

CMyConfig* CMyConfig::GetInstance()
{
	return CMyConfig::m_pInstance;
}
