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

#if defined(_MSC_VER)
    #pragma warning ( disable: 4231 4251 4275 4786 )
#endif

#include <log4cxx/logstring.h>
#include <log4cxx/spi/loggerfactory.h>
#include <log4cxx/hierarchy.h>
#include <log4cxx/defaultloggerfactory.h>
#include <log4cxx/logger.h>
#include <log4cxx/spi/hierarchyeventlistener.h>
#include <log4cxx/level.h>
#include <algorithm>
#include <log4cxx/helpers/loglog.h>
#include <log4cxx/appender.h>
#include <log4cxx/helpers/synchronized.h>
#include <log4cxx/logstring.h>
#include <log4cxx/helpers/stringhelper.h>
#if !defined(LOG4CXX)
    #define LOG4CXX 1
#endif
#include <log4cxx/helpers/aprinitializer.h>
#include <log4cxx/defaultconfigurator.h>
#include <log4cxx/spi/rootlogger.h>
#include <apr_atomic.h>
#include "assert.h"


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

IMPLEMENT_LOG4CXX_OBJECT(Hierarchy)

Hierarchy::Hierarchy() :
    pool(),
    mutex(pool),
    loggers(new LoggerMap()),
    provisionNodes(new ProvisionNodeMap())
{
    synchronized sync(mutex);
    root = new RootLogger(pool, Level::getDebug());
    root->setHierarchy(this);
    defaultFactory = new DefaultLoggerFactory();
    emittedNoAppenderWarning = false;
    configured = false;
    thresholdInt = Level::ALL_INT;
    threshold = Level::getAll();
    emittedNoResourceBundleWarning = false;
}

Hierarchy::~Hierarchy()
{
    // TODO LOGCXX-430
    // https://issues.apache.org/jira/browse/LOGCXX-430?focusedCommentId=15175254&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-15175254
#ifndef APR_HAS_THREADS
    delete loggers;
    delete provisionNodes;
#endif
}

void Hierarchy::addRef() const
{
    ObjectImpl::addRef();
}

void Hierarchy::releaseRef() const
{
    ObjectImpl::releaseRef();
}

void Hierarchy::addHierarchyEventListener(const spi::HierarchyEventListenerPtr& listener)
{
    synchronized sync(mutex);

    if (std::find(listeners.begin(), listeners.end(), listener) != listeners.end())
    {
        LogLog::warn(LOG4CXX_STR("Ignoring attempt to add an existent listener."));
    }
    else
    {
        listeners.push_back(listener);
    }
}

void Hierarchy::clear()
{
    synchronized sync(mutex);
    loggers->clear();
}

void Hierarchy::emitNoAppenderWarning(const LoggerPtr& logger)
{
    bool emitWarning = false;
    {
        synchronized sync(mutex);
        emitWarning = !emittedNoAppenderWarning;
        emittedNoAppenderWarning = true;
    }

    // No appender in hierarchy, warn user only once.
    if (emitWarning)
    {
        LogLog::warn(((LogString) LOG4CXX_STR("No appender could be found for logger ("))
                     + logger->getName() + LOG4CXX_STR(")."));
        LogLog::warn(LOG4CXX_STR("Please initialize the log4cxx system properly."));
    }
}


LoggerPtr Hierarchy::exists(const LogString& name)
{
    synchronized sync(mutex);

    LoggerPtr logger;
    LoggerMap::iterator it = loggers->find(name);

    if (it != loggers->end())
    {
        logger = it->second;
    }


    return logger;
}

void Hierarchy::setThreshold(const LevelPtr& l)
{
    if (l != 0)
    {
        synchronized sync(mutex);
        thresholdInt = l->toInt();
        threshold = l;

        if (thresholdInt != Level::ALL_INT)
        {
            setConfigured(true);
        }
    }
}

void Hierarchy::setThreshold(const LogString& levelStr)
{
    LevelPtr l(Level::toLevelLS(levelStr, 0));

    if (l != 0)
    {
        setThreshold(l);
    }
    else
    {
        LogLog::warn(((LogString) LOG4CXX_STR("No level could be found named \""))
                     + levelStr + LOG4CXX_STR("\"."));
    }
}

void Hierarchy::fireAddAppenderEvent(const LoggerPtr& logger, const AppenderPtr& appender)
{
    setConfigured(true);
    HierarchyEventListenerList clonedList;
    {
        synchronized sync(mutex);
        clonedList = listeners;
    }

    HierarchyEventListenerList::iterator it, itEnd = clonedList.end();
    HierarchyEventListenerPtr listener;

    for (it = clonedList.begin(); it != itEnd; it++)
    {
        listener = *it;
        listener->addAppenderEvent(logger, appender);
    }
}

void Hierarchy::fireRemoveAppenderEvent(const LoggerPtr& logger, const AppenderPtr& appender)

{
    HierarchyEventListenerList clonedList;
    {
        synchronized sync(mutex);
        clonedList = listeners;
    }
    HierarchyEventListenerList::iterator it, itEnd = clonedList.end();
    HierarchyEventListenerPtr listener;

    for (it = clonedList.begin(); it != itEnd; it++)
    {
        listener = *it;
        listener->removeAppenderEvent(logger, appender);
    }
}

const LevelPtr& Hierarchy::getThreshold() const
{
    return threshold;
}

LoggerPtr Hierarchy::getLogger(const LogString& name)
{
    return getLogger(name, defaultFactory);
}

LoggerPtr Hierarchy::getLogger(const LogString& name,
                               const spi::LoggerFactoryPtr& factory)
{
    synchronized sync(mutex);

    LoggerMap::iterator it = loggers->find(name);

    if (it != loggers->end())
    {
        return it->second;
    }
    else
    {
        LoggerPtr logger(factory->makeNewLoggerInstance(pool, name));
        logger->setHierarchy(this);
        loggers->insert(LoggerMap::value_type(name, logger));

        ProvisionNodeMap::iterator it2 = provisionNodes->find(name);

        if (it2 != provisionNodes->end())
        {
            updateChildren(it2->second, logger);
            provisionNodes->erase(it2);
        }

        updateParents(logger);
        return logger;
    }

}

LoggerList Hierarchy::getCurrentLoggers() const
{
    synchronized sync(mutex);

    LoggerList v;
    LoggerMap::const_iterator it, itEnd = loggers->end();

    for (it = loggers->begin(); it != itEnd; it++)
    {
        v.push_back(it->second);
    }


    return v;
}

LoggerPtr Hierarchy::getRootLogger() const
{
    return root;
}

bool Hierarchy::isDisabled(int level) const
{
    if (!configured)
    {
        synchronized sync(mutex);

        if (!configured)
        {
            DefaultConfigurator::configure(
                const_cast<Hierarchy*>(this));
        }
    }

    return thresholdInt > level;
}


void Hierarchy::resetConfiguration()
{
    synchronized sync(mutex);

    getRootLogger()->setLevel(Level::getDebug());
    root->setResourceBundle(0);
    setThreshold(Level::getAll());

    shutdown(); // nested locks are OK

    LoggerList loggers1 = getCurrentLoggers();
    LoggerList::iterator it, itEnd = loggers1.end();

    for (it = loggers1.begin(); it != itEnd; it++)
    {
        LoggerPtr& logger = *it;
        logger->setLevel(0);
        logger->setAdditivity(true);
        logger->setResourceBundle(0);
    }

    //rendererMap.clear();
}

void Hierarchy::shutdown()
{
    synchronized sync(mutex);

    setConfigured(false);

    LoggerPtr root1 = getRootLogger();

    // begin by closing nested appenders
    root1->closeNestedAppenders();

    LoggerList loggers1 = getCurrentLoggers();
    LoggerList::iterator it, itEnd = loggers1.end();

    for (it = loggers1.begin(); it != itEnd; it++)
    {
        LoggerPtr& logger = *it;
        logger->closeNestedAppenders();
    }

    // then, remove all appenders
    root1->removeAllAppenders();

    for (it = loggers1.begin(); it != itEnd; it++)
    {
        LoggerPtr& logger = *it;
        logger->removeAllAppenders();
    }
}


void Hierarchy::updateParents(LoggerPtr logger)
{
    synchronized sync(mutex);
    const LogString name(logger->getName());
    int length = name.size();
    bool parentFound = false;


    // if name = "w.x.y.z", loop through "w.x.y", "w.x" and "w", but not "w.x.y.z"
    for (size_t i = name.find_last_of(0x2E /* '.' */, length - 1);
            (i != LogString::npos) && (i != 0);
            i = name.find_last_of(0x2E /* '.' */, i - 1))
    {
        LogString substr = name.substr(0, i);

        LoggerMap::iterator it = loggers->find(substr);

        if (it != loggers->end())
        {
            parentFound = true;
            logger->parent = it->second;
            break; // no need to update the ancestors of the closest ancestor
        }
        else
        {
            ProvisionNodeMap::iterator it2 = provisionNodes->find(substr);

            if (it2 != provisionNodes->end())
            {
                it2->second.push_back(logger);
            }
            else
            {
                ProvisionNode node(1, logger);
                provisionNodes->insert(
                    ProvisionNodeMap::value_type(substr, node));
            }
        }
    }

    // If we could not find any existing parents, then link with root.
    if (!parentFound)
    {
        logger->parent = root;
    }
}

void Hierarchy::updateChildren(ProvisionNode& pn, LoggerPtr logger)
{

    ProvisionNode::iterator it, itEnd = pn.end();

    for (it = pn.begin(); it != itEnd; it++)
    {
        LoggerPtr& l = *it;

        // Unless this child already points to a correct (lower) parent,
        // make cat.parent point to l.parent and l.parent to cat.
        if (!StringHelper::startsWith(l->parent->name, logger->name))
        {
            logger->parent = l->parent;
            l->parent = logger;
        }
    }
}

void Hierarchy::setConfigured(bool newValue)
{
    synchronized sync(mutex);
    configured = newValue;
}

bool Hierarchy::isConfigured()
{
    return configured;
}
