/*
 * 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.logging.log4j.core.config.plugins.util;

import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.lookup.StrSubstitutor;
import org.apache.logging.log4j.plugins.Node;
import org.apache.logging.log4j.plugins.PluginAliases;
import org.apache.logging.log4j.plugins.PluginFactory;
import org.apache.logging.log4j.plugins.bind.FactoryMethodBinder;
import org.apache.logging.log4j.plugins.bind.FieldConfigurationBinder;
import org.apache.logging.log4j.plugins.bind.MethodConfigurationBinder;
import org.apache.logging.log4j.plugins.inject.ConfigurationInjector;
import org.apache.logging.log4j.plugins.util.Builder;
import org.apache.logging.log4j.plugins.util.PluginType;
import org.apache.logging.log4j.plugins.util.TypeUtil;
import org.apache.logging.log4j.status.StatusLogger;
import org.apache.logging.log4j.util.ReflectionUtil;
import org.apache.logging.log4j.util.StringBuilders;

import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Function;

/**
 * Builder class to instantiate and configure a Plugin object using a PluginFactory method or PluginBuilderFactory
 * builder class.
 */
public class PluginBuilder implements Builder<Object> {

    private static final Logger LOGGER = StatusLogger.getLogger();

    private final PluginType<?> pluginType;
    private final Class<?> clazz;

    private Configuration configuration;
    private Node node;
    private LogEvent event;
    private Substitutor substitutor;
    private final ConcurrentMap<String, Boolean> aliases = new ConcurrentHashMap<>();

    /**
     * Constructs a PluginBuilder for a given PluginType.
     *
     * @param pluginType type of plugin to configure
     */
    public PluginBuilder(final PluginType<?> pluginType) {
        this.pluginType = pluginType;
        this.clazz = pluginType.getPluginClass();
    }

    /**
     * Specifies the Configuration to use for constructing the plugin instance.
     *
     * @param configuration the configuration to use.
     * @return {@code this}
     */
    public PluginBuilder setConfiguration(final Configuration configuration) {
        this.configuration = configuration;
        return this;
    }

    /**
     * Specifies the Node corresponding to the plugin object that will be created.
     *
     * @param node the plugin configuration node to use.
     * @return {@code this}
     */
    public PluginBuilder setConfigurationNode(final Node node) {
        this.node = node;
        return this;
    }

    /**
     * Specifies the LogEvent that may be used to provide extra context for string substitutions.
     *
     * @param event the event to use for extra information.
     * @return {@code this}
     */
    public PluginBuilder forLogEvent(final LogEvent event) {
        this.event = event;
        return this;
    }

    /**
     * Builds the plugin object.
     *
     * @return the plugin object or {@code null} if there was a problem creating it.
     */
    @Override
    public Object build() {
        verify();
        LOGGER.debug("Building Plugin[name={}, class={}].", pluginType.getElementName(),
                pluginType.getPluginClass().getName());
        substitutor = new Substitutor(event);
        // first try to use a builder class if one is available
        try {
            final Builder<?> builder = createBuilder(this.clazz);
            if (builder != null) {
                return injectBuilder(builder);
            }
        } catch (final InvocationTargetException e) {
            LOGGER.error("Could not create plugin builder for plugin {} and element {}", clazz, node.getName(), e.getCause());
            return null;
        } catch (final IllegalAccessException e) {
            LOGGER.error("Could not access plugin builder for plugin {} and element {}", clazz, node.getName());
            return null;
        } catch (final RuntimeException e) { // LOG4J2-1908
            LOGGER.error("Could not create plugin of type {} for element {}", clazz, node.getName(), e);
            return null; // no point in trying the factory method
        }
        // or fall back to factory method if no builder class is available
        try {
            return injectFactoryMethod(findFactoryMethod(this.clazz));
        } catch (final Throwable e) {
            LOGGER.error("Could not create plugin of type {} for element {}: {}", clazz, node.getName(),
                    e.toString(), e);
            return null;
        }
    }

    private void verify() {
        Objects.requireNonNull(this.configuration, "No Configuration object was set.");
        Objects.requireNonNull(this.node, "No Node object was set.");
    }

    private static Builder<?> createBuilder(final Class<?> clazz)
        throws InvocationTargetException, IllegalAccessException {
        for (final Method method : clazz.getDeclaredMethods()) {
            if ((method.isAnnotationPresent(PluginFactory.class)) &&
                Modifier.isStatic(method.getModifiers()) &&
                TypeUtil.isAssignable(Builder.class, method.getReturnType())) {
                ReflectionUtil.makeAccessible(method);
                return (Builder<?>) method.invoke(null);
            } else if (method.isAnnotationPresent(org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory.class) &&
                    Modifier.isStatic(method.getModifiers()) &&
                    TypeUtil.isAssignable(org.apache.logging.log4j.core.util.Builder.class, method.getReturnType())) {
                ReflectionUtil.makeAccessible(method);
                return new BuilderWrapper((org.apache.logging.log4j.core.util.Builder<?>) method.invoke(null));
            }
        }
        return null;
    }

    private Object injectBuilder(final Builder<?> builder) {
        final Object target = builder instanceof BuilderWrapper ? ((BuilderWrapper) builder).getBuilder() : builder;
        final List<Field> fields = TypeUtil.getAllDeclaredFields(target.getClass());
        AccessibleObject.setAccessible(fields.toArray(new Field[0]), true);
        final StringBuilder log = new StringBuilder();
        // TODO: collect OptionBindingExceptions into a composite error message (ConfigurationException?)
        for (final Field field : fields) {
            ConfigurationInjector.forAnnotatedElement(field).ifPresent(injector -> {
                log.append(log.length() == 0 ? simpleName(target) + "(" : ", ");
                injector.withAliases(extractPluginAliases(field.getAnnotations()))
                        .withConversionType(field.getGenericType())
                        .withConfigurationBinder(new FieldConfigurationBinder(field))
                        .withDebugLog(log)
                        .withStringSubstitutionStrategy(substitutor)
                        .withConfiguration(configuration)
                        .withNode(node)
                        .inject(target);
            });
        }
        // TODO: tests
        for (final Method method : target.getClass().getMethods()) {
            ConfigurationInjector.forAnnotatedElement(method).ifPresent(injector -> {
                if (method.getParameterCount() != 1) {
                    throw new IllegalArgumentException("Cannot inject to a plugin builder method with parameter count other than 1");
                }
                log.append(log.length() == 0 ? simpleName(target) + "(" : ", ");
                injector.withAliases(extractPluginAliases(method.getAnnotations()))
                        .withConversionType(method.getGenericParameterTypes()[0])
                        .withConfigurationBinder(new MethodConfigurationBinder(method))
                        .withDebugLog(log)
                        .withStringSubstitutionStrategy(substitutor)
                        .withConfiguration(configuration)
                        .withNode(node)
                        .inject(target);
            });
        }
        log.append(log.length() == 0 ? builder.getClass().getSimpleName() + "()" : ")");
        LOGGER.debug(log.toString());
        checkForRemainingAttributes();
        verifyNodeChildrenUsed();
        return builder.build();
    }

    /**
     * {@code object.getClass().getSimpleName()} returns {@code Builder}, when we want {@code PatternLayout$Builder}.
     */
    private static String simpleName(final Object object) {
        if (object == null) {
            return "null";
        }
        final String cls = object.getClass().getName();
        final int index = cls.lastIndexOf('.');
        return index < 0 ? cls : cls.substring(index + 1);
    }

    private static Method findFactoryMethod(final Class<?> clazz) {
        for (final Method method : clazz.getDeclaredMethods()) {
            if ((method.isAnnotationPresent(PluginFactory.class) ||
                 method.isAnnotationPresent(org.apache.logging.log4j.core.config.plugins.PluginFactory.class)) &&
                Modifier.isStatic(method.getModifiers())) {
                ReflectionUtil.makeAccessible(method);
                return method;
            }
        }
        throw new IllegalStateException("No factory method found for class " + clazz.getName());
    }

    private Object injectFactoryMethod(final Method factory) throws Throwable {
        final StringBuilder log = new StringBuilder();
        final FactoryMethodBinder binder = new FactoryMethodBinder(factory);
        binder.forEachParameter((parameter, optionBinder) -> {
            log.append(log.length() == 0 ? factory.getName() + "(" : ", ");
            ConfigurationInjector.forAnnotatedElement(parameter).ifPresent(injector -> injector
                            .withAliases(extractPluginAliases(parameter.getAnnotations()))
                            .withConversionType(parameter.getParameterizedType())
                            .withConfigurationBinder(optionBinder)
                            .withDebugLog(log)
                            .withStringSubstitutionStrategy(substitutor)
                            .withConfiguration(configuration)
                            .withNode(node)
                            .inject(binder));
        });
        log.append(log.length() == 0 ? factory.getName() + "()" : ")");
        checkForRemainingAttributes();
        verifyNodeChildrenUsed();
        LOGGER.debug(log.toString());
        return binder.invoke();
    }

    private static String[] extractPluginAliases(final Annotation... parmTypes) {
        String[] aliases = {};
        for (final Annotation a : parmTypes) {
            if (a instanceof PluginAliases) {
                aliases = ((PluginAliases) a).value();
            } else if (a instanceof org.apache.logging.log4j.core.config.plugins.PluginAliases) {
                aliases = ((org.apache.logging.log4j.core.config.plugins.PluginAliases) a).value();
            }
        }
        return aliases;
    }

    private void checkForRemainingAttributes() {
        final Map<String, String> attrs = node.getAttributes();
        if (!attrs.isEmpty()) {
            final StringBuilder sb = new StringBuilder();
            for (final String key : attrs.keySet()) {
                if (sb.length() == 0) {
                    sb.append(node.getName());
                    sb.append(" contains ");
                    if (attrs.size() == 1) {
                        sb.append("an invalid element or attribute ");
                    } else {
                        sb.append("invalid attributes ");
                    }
                } else {
                    sb.append(", ");
                }
                StringBuilders.appendDqValue(sb, key);
            }
            LOGGER.error(sb.toString());
        }
    }

    private void verifyNodeChildrenUsed() {
        final List<Node> children = node.getChildren();
        if (!(pluginType.isDeferChildren() || children.isEmpty())) {
            for (final Node child : children) {
                final String nodeType = node.getType().getElementName();
                final String start = nodeType.equals(node.getName()) ? node.getName() : nodeType + ' ' + node.getName();
                LOGGER.error("{} has no parameter that matches element {}", start, child.getName());
            }
        }
    }

    private class Substitutor implements Function<String, String> {
        private final LogEvent event;
        private final StrSubstitutor strSubstitutor;

        Substitutor(LogEvent event) {
            this.event = event;
            this.strSubstitutor = configuration.getStrSubstitutor();
        }

        @Override
        public String apply(String str) {
            return strSubstitutor.replace(event, str);
        }
    }

    public static class BuilderWrapper<T> implements Builder<T> {
        private final org.apache.logging.log4j.core.util.Builder<T> builder;

        BuilderWrapper(org.apache.logging.log4j.core.util.Builder<T> builder) {
            this.builder = builder;
        }

        public T build() {
            return builder.build();
        }

        org.apache.logging.log4j.core.util.Builder<T> getBuilder() {
            return builder;
        }
    }
}
