/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <log4cxx/logstring.h>
#include <log4cxx/spi/loggerfactory.h>
#include <log4cxx/spi/loggerrepository.h>
#include <log4cxx/appenderskeleton.h>
#include <log4cxx/helpers/optionconverter.h>
#include <algorithm>
#include <ctype.h>
#include <log4cxx/helpers/stringhelper.h>
#include <log4cxx/helpers/exception.h>
#include <stdlib.h>
#include <log4cxx/helpers/properties.h>
#include <log4cxx/helpers/loglog.h>
#include <log4cxx/level.h>
#include <log4cxx/helpers/object.h>
#include <log4cxx/helpers/class.h>
#include <log4cxx/helpers/loader.h>
#include <log4cxx/helpers/system.h>
#include <log4cxx/propertyconfigurator.h>
#include <log4cxx/helpers/transcoder.h>
#include <log4cxx/file.h>
#include <log4cxx/xml/domconfigurator.h>

using namespace log4cxx;
using namespace log4cxx::helpers;
using namespace log4cxx::spi;


LogString OptionConverter::convertSpecialChars(const LogString& s)
{
	logchar c;
	LogString sbuf;

	LogString::const_iterator i = s.begin();

	while (i != s.end())
	{
		c = *i++;

		if (c == 0x5C /* '\\' */)
		{
			c =  *i++;

			switch (c)
			{
				case 0x6E: //'n'
					c = 0x0A;
					break;

				case 0x72: //'r'
					c = 0x0D;
					break;

				case 0x74: //'t'
					c = 0x09;
					break;

				case 0x66: //'f'
					c = 0x0C;
					break;

				default:
					break;
			}
		}

		sbuf.append(1, c);
	}

	return sbuf;
}


bool OptionConverter::toBoolean(const LogString& value, bool dEfault)
{
	if (value.length() >= 4)
	{
		if (StringHelper::equalsIgnoreCase(value.substr(0, 4),
				LOG4CXX_STR("TRUE"), LOG4CXX_STR("true")))
		{
			return true;
		}
	}

	if (dEfault && value.length() >= 5)
	{
		if (StringHelper::equalsIgnoreCase(value.substr(0, 5),
				LOG4CXX_STR("FALSE"), LOG4CXX_STR("false")))
		{
			return false;
		}
	}

	return dEfault;
}

int OptionConverter::toInt(const LogString& value, int dEfault)
{
	LogString trimmed(StringHelper::trim(value));

	if (trimmed.empty())
	{
		return dEfault;
	}

	LOG4CXX_ENCODE_CHAR(cvalue, trimmed);

	return (int) atol(cvalue.c_str());
}

long OptionConverter::toFileSize(const LogString& s, long dEfault)
{
	if (s.empty())
	{
		return dEfault;
	}

	size_t index = s.find_first_of(LOG4CXX_STR("bB"));

	if (index != LogString::npos && index > 0)
	{
		long multiplier = 1;
		index--;

		if (s[index] == 0x6B /* 'k' */ || s[index] == 0x4B /* 'K' */)
		{
			multiplier = 1024;
		}
		else if (s[index] == 0x6D /* 'm' */ || s[index] == 0x4D /* 'M' */)
		{
			multiplier = 1024 * 1024;
		}
		else if (s[index] == 0x67 /* 'g'*/ || s[index] == 0x47 /* 'G' */)
		{
			multiplier = 1024 * 1024 * 1024;
		}

		return toInt(s.substr(0, index), 1) * multiplier;
	}

	return toInt(s, 1);
}

LogString OptionConverter::findAndSubst(const LogString& key, Properties& props)
{
	LogString value(props.getProperty(key));

	if (value.empty())
	{
		return value;
	}

	try
	{
		return substVars(value, props);
	}
	catch (IllegalArgumentException& e)
	{
		LogLog::error(((LogString) LOG4CXX_STR("Bad option value ["))
			+ value + LOG4CXX_STR("]."), e);
		return value;
	}
}

LogString OptionConverter::substVars(const LogString& val, Properties& props)
{
	LogString sbuf;
	const logchar delimStartArray[] = { 0x24, 0x7B, 0 };
	const LogString delimStart(delimStartArray);
	const logchar delimStop = 0x7D; // '}';
	const size_t DELIM_START_LEN = 2;
	const size_t DELIM_STOP_LEN = 1;

	size_t i = 0;

	while (true)
	{
		size_t j = val.find(delimStart, i);

		if (j == val.npos)
		{
			// no more variables
			if (i == 0)
			{
				// this is a simple string
				return val;
			}
			else
			{
				// add the tail string which contails no variables and return the result.
				sbuf.append(val.substr(i, val.length() - i));
				return sbuf;
			}
		}
		else
		{
			sbuf.append(val.substr(i, j - i));
			size_t k = val.find(delimStop, j);

			if (k == val.npos)
			{
				LogString msg(1, (logchar) 0x22 /* '\"' */);
				msg.append(val);
				msg.append(LOG4CXX_STR("\" has no closing brace. Opening brace at position "));
				Pool p;
				StringHelper::toString(j, p, msg);
				msg.append(1, (logchar) 0x2E /* '.' */);
				throw IllegalArgumentException(msg);
			}
			else
			{
				j += DELIM_START_LEN;
				LogString key = val.substr(j, k - j);
				// first try in System properties
				LogString replacement(getSystemProperty(key, LogString()));

				// then try props parameter
				if (replacement.empty())
				{
					replacement = props.getProperty(key);
				}

				if (!replacement.empty())
				{
					// Do variable substitution on the replacement string
					// such that we can solve "Hello ${x2}" as "Hello p1"
					// the where the properties are
					// x1=p1
					// x2=${x1}
					LogString recursiveReplacement = substVars(replacement, props);
					sbuf.append(recursiveReplacement);
				}

				i = k + DELIM_STOP_LEN;
			}
		}
	}
}

LogString OptionConverter::getSystemProperty(const LogString& key, const LogString& def)
{
	if (!key.empty())
	{
		LogString value(System::getProperty(key));

		if (!value.empty())
		{
			return value;
		}
	}

	return def;
}

LevelPtr OptionConverter::toLevel(const LogString& value,
	const LevelPtr& defaultValue)
{
	size_t hashIndex = value.find(LOG4CXX_STR("#"));

	if (hashIndex == LogString::npos)
	{
		if (value.empty())
		{
			return defaultValue;
		}
		else
		{
			LogLog::debug(
				((LogString) LOG4CXX_STR("OptionConverter::toLevel: no class name specified, level=["))
				+ value
				+ LOG4CXX_STR("]"));
			// no class name specified : use standard Level class
			return Level::toLevelLS(value, defaultValue);
		}
	}

	LogString clazz = value.substr(hashIndex + 1);
	LogString levelName = value.substr(0, hashIndex);
	LogLog::debug(((LogString) LOG4CXX_STR("OptionConverter::toLevel: class=["))
		+ clazz + LOG4CXX_STR("], level=[") + levelName + LOG4CXX_STR("]"));

	// This is degenerate case but you never know.
	if (levelName.empty())
	{
		return Level::toLevelLS(value, defaultValue);
	}

	try
	{
		Level::LevelClass& levelClass =
			(Level::LevelClass&)Loader::loadClass(clazz);
		return levelClass.toLevel(levelName);
	}
	catch (ClassNotFoundException&)
	{
		LogLog::warn(((LogString) LOG4CXX_STR("custom level class ["))
			+ clazz + LOG4CXX_STR("] not found."));
	}
	catch (Exception& oops)
	{
		LogLog::warn(
			LOG4CXX_STR("class [") + clazz + LOG4CXX_STR("], level [") + levelName +
			LOG4CXX_STR("] conversion) failed."), oops);
	}
	catch (...)
	{
		LogLog::warn(
			LOG4CXX_STR("class [") + clazz + LOG4CXX_STR("], level [") + levelName +
			LOG4CXX_STR("] conversion) failed."));
	}

	return defaultValue;
}


ObjectPtr OptionConverter::instantiateByKey(Properties& props, const LogString& key,
	const Class& superClass, const ObjectPtr& defaultValue)
{
	// Get the value of the property in string form
	LogString className(findAndSubst(key, props));

	if (className.empty())
	{
		LogLog::error(
			((LogString) LOG4CXX_STR("Could not find value for key ")) + key);
		return defaultValue;
	}

	// Trim className to avoid trailing spaces that cause problems.
	return OptionConverter::instantiateByClassName(
			StringHelper::trim(className), superClass, defaultValue);
}

ObjectPtr OptionConverter::instantiateByClassName(const LogString& className,
	const Class& superClass, const ObjectPtr& defaultValue)
{
	if (!className.empty())
	{
		try
		{
			const Class& classObj = Loader::loadClass(className);
			ObjectPtr newObject =  classObj.newInstance();

			if (!newObject->instanceof(superClass))
			{
				return defaultValue;
			}

			return newObject;
		}
		catch (Exception& e)
		{
			LogLog::error(LOG4CXX_STR("Could not instantiate class [") +
				className + LOG4CXX_STR("]."), e);
		}
	}

	return defaultValue;
}

void OptionConverter::selectAndConfigure(const File& configFileName,
	const LogString& _clazz, spi::LoggerRepositoryPtr& hierarchy)
{
	ConfiguratorPtr configurator;
	LogString clazz = _clazz;

	LogString filename(configFileName.getPath());

	if (clazz.empty()
		&& filename.length() > 4
		&& StringHelper::equalsIgnoreCase(
			filename.substr(filename.length() - 4),
			LOG4CXX_STR(".XML"), LOG4CXX_STR(".xml")))
	{
		clazz = log4cxx::xml::DOMConfigurator::getStaticClass().toString();
	}

	if (!clazz.empty())
	{
		LogLog::debug(LOG4CXX_STR("Preferred configurator class: ") + clazz);
		configurator = instantiateByClassName(clazz,
				Configurator::getStaticClass(),
				0);

		if (configurator == 0)
		{
			LogLog::error(LOG4CXX_STR("Could not instantiate configurator [")
				+ clazz + LOG4CXX_STR("]."));
			return;
		}
	}
	else
	{
		configurator = new PropertyConfigurator();
	}

	configurator->doConfigure(configFileName, hierarchy);
}
