/*
 * 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/level.h>
#include <log4cxx/helpers/stringhelper.h>
#include <log4cxx/helpers/transcoder.h>
#if !defined(LOG4CXX)
	#define LOG4CXX 1
#endif
#include <log4cxx/helpers/aprinitializer.h>

using namespace log4cxx;
using namespace log4cxx::helpers;

IMPLEMENT_LOG4CXX_OBJECT_WITH_CUSTOM_CLASS(Level, LevelClass)

volatile bool Level::initialized = false;
log4cxx::mutex Level::initMutex;
LevelPtr Level::allLevel;
LevelPtr Level::fatalLevel;
LevelPtr Level::errorLevel;
LevelPtr Level::warnLevel;
LevelPtr Level::infoLevel;
LevelPtr Level::debugLevel;
LevelPtr Level::traceLevel;
LevelPtr Level::offLevel;

void Level::initializeLevels(){
    if( initialized ){
        return;
    }

	log4cxx::unique_lock<log4cxx::mutex> lock(initMutex);
    if( initialized ){
        return;
    }

    allLevel   = LevelPtr(new Level(Level::ALL_INT, LOG4CXX_STR("ALL"), 7));
    fatalLevel = LevelPtr(new Level(Level::FATAL_INT, LOG4CXX_STR("FATAL"), 0));
    errorLevel = LevelPtr(new Level(Level::ERROR_INT, LOG4CXX_STR("ERROR"), 3));
    warnLevel  = LevelPtr(new Level(Level::WARN_INT, LOG4CXX_STR("WARN"), 4));
    infoLevel  = LevelPtr(new Level(Level::INFO_INT, LOG4CXX_STR("INFO"), 6));
    debugLevel = LevelPtr(new Level(Level::DEBUG_INT, LOG4CXX_STR("DEBUG"), 7));
    traceLevel = LevelPtr(new Level(Level::TRACE_INT, LOG4CXX_STR("TRACE"), 7));
    offLevel   = LevelPtr(new Level(Level::OFF_INT, LOG4CXX_STR("OFF"), 0));

    initialized = true;
}

LevelPtr Level::getOff()
{
    initializeLevels();
    return offLevel;
}

LevelPtr Level::getFatal()
{
    initializeLevels();
    return fatalLevel;
}

LevelPtr Level::getError()
{
    initializeLevels();
    return errorLevel;
}

LevelPtr Level::getWarn()
{
    initializeLevels();
    return warnLevel;
}

LevelPtr Level::getInfo()
{
    initializeLevels();
    return infoLevel;
}

LevelPtr Level::getDebug()
{
    initializeLevels();
    return debugLevel;
}

LevelPtr Level::getTrace()
{
    initializeLevels();
    return traceLevel;
}


LevelPtr Level::getAll()
{
    initializeLevels();
    return allLevel;
}



Level::Level(int level1,
	const LogString& name1, int syslogEquivalent1)
	: level(level1), name(name1), syslogEquivalent(syslogEquivalent1)
{
    APRInitializer::initialize();
}


LevelPtr Level::toLevelLS(const LogString& sArg)
{
	return toLevelLS(sArg, Level::getDebug());
}

LogString Level::toString() const
{
	return name;
}


LevelPtr Level::toLevel(int val)
{
	return toLevel(val, Level::getDebug());
}

LevelPtr Level::toLevel(int val, const LevelPtr& defaultLevel)
{
	switch (val)
	{
		case ALL_INT:
			return getAll();

		case DEBUG_INT:
			return getDebug();

		case TRACE_INT:
			return getTrace();

		case INFO_INT:
			return getInfo();

		case WARN_INT:
			return getWarn();

		case ERROR_INT:
			return getError();

		case FATAL_INT:
			return getFatal();

		case OFF_INT:
			return getOff();

		default:
			return defaultLevel;
	}
}

LevelPtr Level::toLevel(const std::string& sArg)
{
	return toLevel(sArg, Level::getDebug());
}

LevelPtr Level::toLevel(const std::string& sArg, const LevelPtr& defaultLevel)
{
	LOG4CXX_DECODE_CHAR(s, sArg);
	return toLevelLS(s, defaultLevel);
}

void Level::toString(std::string& dst) const
{
	Transcoder::encode(name, dst);
}

#if LOG4CXX_WCHAR_T_API
LevelPtr Level::toLevel(const std::wstring& sArg)
{
	return toLevel(sArg, Level::getDebug());
}

LevelPtr Level::toLevel(const std::wstring& sArg, const LevelPtr& defaultLevel)
{
	LOG4CXX_DECODE_WCHAR(s, sArg);
	return toLevelLS(s, defaultLevel);
}

void Level::toString(std::wstring& dst) const
{
	Transcoder::encode(name, dst);
}

#endif

#if LOG4CXX_UNICHAR_API
LevelPtr Level::toLevel(const std::basic_string<UniChar>& sArg)
{
	return toLevel(sArg, Level::getDebug());
}

LevelPtr Level::toLevel(const std::basic_string<UniChar>& sArg, const LevelPtr& defaultLevel)
{
	LOG4CXX_DECODE_UNICHAR(s, sArg);
	return toLevelLS(s, defaultLevel);
}

void Level::toString(std::basic_string<UniChar>& dst) const
{
	Transcoder::encode(name, dst);
}

#endif

#if LOG4CXX_CFSTRING_API
LevelPtr Level::toLevel(const CFStringRef& sArg)
{
	return toLevel(sArg, Level::getDebug());
}

LevelPtr Level::toLevel(const CFStringRef& sArg, const LevelPtr& defaultLevel)
{
	LogString s;
	Transcoder::decode(sArg, s);
	return toLevelLS(s, defaultLevel);
}

void Level::toString(CFStringRef& dst) const
{
	dst = Transcoder::encode(name);
}
#endif


LevelPtr Level::toLevelLS(const LogString& sArg, const LevelPtr& defaultLevel)
{
	const LogString trimmed(StringHelper::trim(sArg));
	const size_t len = trimmed.length();

	if (len == 4)
	{
		if (StringHelper::equalsIgnoreCase(trimmed, LOG4CXX_STR("INFO"), LOG4CXX_STR("info")))
		{
			return getInfo();
		}

		if (StringHelper::equalsIgnoreCase(trimmed, LOG4CXX_STR("WARN"), LOG4CXX_STR("warn")))
		{
			return getWarn();
		}
	}
	else
	{
		if (len == 5)
		{
			if (StringHelper::equalsIgnoreCase(trimmed, LOG4CXX_STR("DEBUG"), LOG4CXX_STR("debug")))
			{
				return getDebug();
			}

			if (StringHelper::equalsIgnoreCase(trimmed, LOG4CXX_STR("TRACE"), LOG4CXX_STR("trace")))
			{
				return getTrace();
			}

			if (StringHelper::equalsIgnoreCase(trimmed, LOG4CXX_STR("ERROR"), LOG4CXX_STR("error")))
			{
				return getError();
			}

			if (StringHelper::equalsIgnoreCase(trimmed, LOG4CXX_STR("FATAL"), LOG4CXX_STR("fatal")))
			{
				return getFatal();
			}
		}
		else
		{
			if (len == 3)
			{
				if (StringHelper::equalsIgnoreCase(trimmed, LOG4CXX_STR("OFF"), LOG4CXX_STR("off")))
				{
					return getOff();
				}

				if (StringHelper::equalsIgnoreCase(trimmed, LOG4CXX_STR("ALL"), LOG4CXX_STR("all")))
				{
					return getAll();
				}
			}
		}
	}

	return defaultLevel;
}


bool Level::equals(const LevelPtr& level1) const
{
	return (this->level == level1->level);
}

bool Level::isGreaterOrEqual(const LevelPtr& level1) const
{
	return this->level >= level1->level;
}

