/*
 *
 * 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.
 *
 */
package org.apache.qpid.server.logging.logback;

import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Appender;
import ch.qos.logback.core.Context;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.qpid.server.logging.LogInclusionRule;
import org.apache.qpid.server.model.AbstractConfigurationChangeListener;
import org.apache.qpid.server.model.AbstractConfiguredObject;
import org.apache.qpid.server.model.BrokerLogInclusionRule;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.ConfiguredObjectTypeRegistry;
import org.apache.qpid.server.model.ManagedObject;
import org.apache.qpid.server.model.State;
import org.apache.qpid.server.model.StateTransition;
import org.apache.qpid.server.model.VirtualHostLogInclusionRule;
import org.apache.qpid.server.plugin.ConfiguredObjectRegistration;
import org.apache.qpid.server.plugin.QpidServiceLoader;

public abstract class AbstractLogger<X extends AbstractLogger<X>> extends AbstractConfiguredObject<X>
{
    private final static ch.qos.logback.classic.Logger ROOT_LOGGER = ((ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME));

    private final CompositeFilter _compositeFilter = new CompositeFilter();

    protected AbstractLogger(Map<String, Object> attributes, ConfiguredObject<?> parent)
    {
        super(parentsMap(parent), attributes);
        addChangeListener(new LogInclusionRuleListener());
    }

    protected final void addLogInclusionRule(LogBackLogInclusionRule logInclusionRule)
    {
        _compositeFilter.addLogInclusionRule(logInclusionRule);
    }

    protected final void removeLogInclusionRule(LogBackLogInclusionRule logInclusionRule)
    {
        _compositeFilter.removeLogInclusionRule(logInclusionRule);
    }

    @Override
    protected void postResolveChildren()
    {
        super.postResolveChildren();

        LoggerContext loggerContext = ROOT_LOGGER.getLoggerContext();
        Appender<ILoggingEvent> appender = createAppenderInstance(loggerContext);
        appender.setName(getName());
        appender.setContext(loggerContext);

        for(LogInclusionRule logInclusionRule : getLogInclusionRules())
        {
            _compositeFilter.addLogInclusionRule((LogBackLogInclusionRule)logInclusionRule);
        }
        appender.addFilter(_compositeFilter);

        ROOT_LOGGER.addAppender(appender);
        appender.start();

        // TODO generalise for virtualhost too
        StartupAppender startupAppender = (StartupAppender) ROOT_LOGGER.getAppender(StartupAppender.class.getName());
        if (startupAppender != null)
        {
            startupAppender.replayAccumulatedEvents(appender);
        }
    }

    protected abstract Appender<ILoggingEvent> createAppenderInstance(Context context);

    protected abstract Collection<? extends LogInclusionRule> getLogInclusionRules();

    @StateTransition( currentState = { State.ERRORED, State.UNINITIALIZED, State.STOPPED }, desiredState = State.ACTIVE )
    private ListenableFuture<Void> doActivate()
    {
        setState(State.ACTIVE);
        return Futures.immediateFuture(null);
    }

    @StateTransition(currentState = {State.ACTIVE, State.UNINITIALIZED, State.ERRORED, State.STOPPED}, desiredState = State.DELETED)
    private ListenableFuture<Void> doDelete()
    {
        return doAfterAlways(closeAsync(), new Runnable()
        {
            @Override
            public void run()
            {
                deleted();
                setState(State.DELETED);
                stopLogging();
            }
        });
    }

    @Override
    protected <C extends ConfiguredObject> ListenableFuture<C> addChildAsync(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents)
    {
        return getObjectFactory().createAsync(childClass, attributes, this);
    }

    public final long getErrorCount()
    {
        return _compositeFilter.getErrorCount();
    }

    public final long getWarnCount()
    {
        return _compositeFilter.getWarnCount();
    }

    public void stopLogging()
    {
        Appender appender = ROOT_LOGGER.getAppender(getName());
        if (appender != null)
        {
            appender.stop();
            ROOT_LOGGER.detachAppender(appender);
        }
    }

    private class LogInclusionRuleListener extends AbstractConfigurationChangeListener
    {

        @Override
        public void childAdded(final ConfiguredObject<?> object, final ConfiguredObject<?> child)
        {
            if (child instanceof LogBackLogInclusionRule)
            {
                addLogInclusionRule((LogBackLogInclusionRule) child);
            }
        }

        @Override
        public void childRemoved(final ConfiguredObject<?> object, final ConfiguredObject<?> child)
        {
            if (child instanceof LogBackLogInclusionRule)
            {
                removeLogInclusionRule((LogBackLogInclusionRule) child);
            }
        }

    }

    public static Map<String, Collection<String>> getSupportedVirtualHostLoggerChildTypes()
    {
        return getSupportedLoggerChildTypes(VirtualHostLogInclusionRule.class);
    }

    public static Map<String, Collection<String>> getSupportedBrokerLoggerChildTypes()
    {
        return getSupportedLoggerChildTypes(BrokerLogInclusionRule.class);
    }

    private static Map<String, Collection<String>> getSupportedLoggerChildTypes(Class<? extends ConfiguredObject> clazz)
    {
        return Collections.singletonMap(clazz.getSimpleName(), getSupportedLogInclusionRules(clazz));
    }


    private static Collection<String> getSupportedLogInclusionRules(Class<? extends ConfiguredObject> clazz)
    {

        final Iterable<ConfiguredObjectRegistration> registrations =
                (new QpidServiceLoader()).instancesOf(ConfiguredObjectRegistration.class);

        Set<String> supportedTypes = new HashSet<>();

        for(ConfiguredObjectRegistration registration : registrations)
        {
            for(Class<? extends ConfiguredObject> typeClass : registration.getConfiguredObjectClasses())
            {
                if(clazz.isAssignableFrom(typeClass))
                {
                    ManagedObject annotation = typeClass.getAnnotation(ManagedObject.class);

                    if (annotation.creatable() && annotation.defaultType().equals("") && LogBackLogInclusionRule.class.isAssignableFrom(typeClass))
                    {
                        supportedTypes.add(ConfiguredObjectTypeRegistry.getType(typeClass));
                    }
                }
            }
        }
        return Collections.unmodifiableCollection(supportedTypes);
    }

}
