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

import java.util.Map;
import java.util.Properties;
import java.util.concurrent.TimeUnit;

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.ConfigurationException;
import org.apache.logging.log4j.core.config.ConfigurationSource;
import org.apache.logging.log4j.core.config.LoggerConfig;
import org.apache.logging.log4j.core.config.builder.api.AppenderComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.AppenderRefComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.ComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
import org.apache.logging.log4j.core.config.builder.api.FilterComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.FilterableComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.LayoutComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.LoggableComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.LoggerComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.RootLoggerComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.ScriptComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.ScriptFileComponentBuilder;
import org.apache.logging.log4j.core.filter.AbstractFilter.AbstractFilterBuilder;
import org.apache.logging.log4j.plugins.util.Builder;
import org.apache.logging.log4j.util.PropertiesUtil;
import org.apache.logging.log4j.util.Strings;

/**
 * Helper builder for parsing properties files into a PropertiesConfiguration.
 *
 * @since 2.6
 */
public class PropertiesConfigurationBuilder extends ConfigurationBuilderFactory
    implements Builder<PropertiesConfiguration> {

    private static final String ADVERTISER_KEY = "advertiser";
    private static final String STATUS_KEY = "status";
    private static final String SHUTDOWN_HOOK = "shutdownHook";
    private static final String SHUTDOWN_TIMEOUT = "shutdownTimeout";
    private static final String VERBOSE = "verbose";
    private static final String DEST = "dest";
    private static final String PACKAGES = "packages";
    private static final String CONFIG_NAME = "name";
    private static final String MONITOR_INTERVAL = "monitorInterval";
    private static final String CONFIG_TYPE = "type";

    private final ConfigurationBuilder<PropertiesConfiguration> builder;
    private LoggerContext loggerContext;
    private Properties rootProperties;

    public PropertiesConfigurationBuilder() {
        this.builder = newConfigurationBuilder(PropertiesConfiguration.class);
    }

    public PropertiesConfigurationBuilder setRootProperties(final Properties rootProperties) {
        this.rootProperties = rootProperties;
        return this;
    }

    public PropertiesConfigurationBuilder setConfigurationSource(final ConfigurationSource source) {
        builder.setConfigurationSource(source);
        return this;
    }

    @Override
    public PropertiesConfiguration build() {
        for (final String key : rootProperties.stringPropertyNames()) {
            if (!key.contains(".")) {
                builder.addRootProperty(key, rootProperties.getProperty(key));
            }
        }
        builder
            .setStatusLevel(Level.toLevel(rootProperties.getProperty(STATUS_KEY), Level.ERROR))
            .setShutdownHook(rootProperties.getProperty(SHUTDOWN_HOOK))
            .setShutdownTimeout(Long.parseLong(rootProperties.getProperty(SHUTDOWN_TIMEOUT, "0")), TimeUnit.MILLISECONDS)
            .setVerbosity(rootProperties.getProperty(VERBOSE))
            .setDestination(rootProperties.getProperty(DEST))
            .setPackages(rootProperties.getProperty(PACKAGES))
            .setConfigurationName(rootProperties.getProperty(CONFIG_NAME))
            .setMonitorInterval(rootProperties.getProperty(MONITOR_INTERVAL, "0"))
            .setAdvertiser(rootProperties.getProperty(ADVERTISER_KEY));

        final Properties propertyPlaceholders = PropertiesUtil.extractSubset(rootProperties, "property");
        for (final String key : propertyPlaceholders.stringPropertyNames()) {
            builder.addProperty(key, propertyPlaceholders.getProperty(key));
        }

        final Map<String, Properties> scripts = PropertiesUtil.partitionOnCommonPrefixes(
            PropertiesUtil.extractSubset(rootProperties, "script"));
        for (final Map.Entry<String, Properties> entry : scripts.entrySet()) {
            final Properties scriptProps = entry.getValue();
            final String type = (String) scriptProps.remove("type");
            if (type == null) {
                throw new ConfigurationException("No type provided for script - must be Script or ScriptFile");
            }
            if (type.equalsIgnoreCase("script")) {
                builder.add(createScript(scriptProps));
            } else {
                builder.add(createScriptFile(scriptProps));
            }
        }

        final Properties levelProps = PropertiesUtil.extractSubset(rootProperties, "customLevel");
        if (levelProps.size() > 0) {
            for (final String key : levelProps.stringPropertyNames()) {
                builder.add(builder.newCustomLevel(key, Integer.parseInt(levelProps.getProperty(key))));
            }
        }

        final String filterProp = rootProperties.getProperty("filters");
        if (filterProp != null) {
            final String[] filterNames = filterProp.split(",");
            for (final String filterName : filterNames) {
                final String name = filterName.trim();
                builder.add(createFilter(name, PropertiesUtil.extractSubset(rootProperties, "filter." + name)));
            }
        } else {

            final Map<String, Properties> filters = PropertiesUtil
                    .partitionOnCommonPrefixes(PropertiesUtil.extractSubset(rootProperties, "filter"));
            for (final Map.Entry<String, Properties> entry : filters.entrySet()) {
                builder.add(createFilter(entry.getKey().trim(), entry.getValue()));
            }
        }

        final String appenderProp = rootProperties.getProperty("appenders");
        if (appenderProp != null) {
            final String[] appenderNames = appenderProp.split(",");
            for (final String appenderName : appenderNames) {
                final String name = appenderName.trim();
                builder.add(createAppender(appenderName.trim(),
                        PropertiesUtil.extractSubset(rootProperties, "appender." + name)));
            }
        } else {
            final Map<String, Properties> appenders = PropertiesUtil
                    .partitionOnCommonPrefixes(PropertiesUtil.extractSubset(rootProperties, Appender.ELEMENT_TYPE));
            for (final Map.Entry<String, Properties> entry : appenders.entrySet()) {
                builder.add(createAppender(entry.getKey().trim(), entry.getValue()));
            }
        }

        final String loggerProp = rootProperties.getProperty("loggers");
        if (loggerProp != null) {
            final String[] loggerNames = loggerProp.split(",");
            for (final String loggerName : loggerNames) {
                final String name = loggerName.trim();
                if (!name.equals(LoggerConfig.ROOT)) {
                    builder.add(createLogger(name, PropertiesUtil.extractSubset(rootProperties, "logger." +
                            name)));
                }
            }
        } else {
            final Map<String, Properties> loggers = PropertiesUtil
                    .partitionOnCommonPrefixes(PropertiesUtil.extractSubset(rootProperties, "logger"));
            for (final Map.Entry<String, Properties> entry : loggers.entrySet()) {
                final String name = entry.getKey().trim();
                if (!name.equals(LoggerConfig.ROOT)) {
                    builder.add(createLogger(name, entry.getValue()));
                }
            }
        }

        final Properties props = PropertiesUtil.extractSubset(rootProperties, "rootLogger");
        if (props.size() > 0) {
            builder.add(createRootLogger(props));
        }
        
        builder.setLoggerContext(loggerContext);
        
        return builder.build(false);
    }

    private ScriptComponentBuilder createScript(final Properties properties) {
        final String name = (String) properties.remove("name");
        final String language = (String) properties.remove("language");
        final String text = (String) properties.remove("text");
        final ScriptComponentBuilder scriptBuilder = builder.newScript(name, language, text);
        return processRemainingProperties(scriptBuilder, properties);
    }


    private ScriptFileComponentBuilder createScriptFile(final Properties properties) {
        final String name = (String) properties.remove("name");
        final String path = (String) properties.remove("path");
        final ScriptFileComponentBuilder scriptFileBuilder = builder.newScriptFile(name, path);
        return processRemainingProperties(scriptFileBuilder, properties);
    }

    private AppenderComponentBuilder createAppender(final String key, final Properties properties) {
        final String name = (String) properties.remove(CONFIG_NAME);
        if (Strings.isEmpty(name)) {
            throw new ConfigurationException("No name attribute provided for Appender " + key);
        }
        final String type = (String) properties.remove(CONFIG_TYPE);
        if (Strings.isEmpty(type)) {
            throw new ConfigurationException("No type attribute provided for Appender " + key);
        }
        final AppenderComponentBuilder appenderBuilder = builder.newAppender(name, type);
        addFiltersToComponent(appenderBuilder, properties);
        final Properties layoutProps = PropertiesUtil.extractSubset(properties, "layout");
        if (layoutProps.size() > 0) {
            appenderBuilder.add(createLayout(name, layoutProps));
        }

        return processRemainingProperties(appenderBuilder, properties);
    }

    private FilterComponentBuilder createFilter(final String key, final Properties properties) {
        final String type = (String) properties.remove(CONFIG_TYPE);
        if (Strings.isEmpty(type)) {
            throw new ConfigurationException("No type attribute provided for Filter " + key);
        }
        final String onMatch = (String) properties.remove(AbstractFilterBuilder.ATTR_ON_MATCH);
        final String onMismatch = (String) properties.remove(AbstractFilterBuilder.ATTR_ON_MISMATCH);
        final FilterComponentBuilder filterBuilder = builder.newFilter(type, onMatch, onMismatch);
        return processRemainingProperties(filterBuilder, properties);
    }

    private AppenderRefComponentBuilder createAppenderRef(final String key, final Properties properties) {
        final String ref = (String) properties.remove("ref");
        if (Strings.isEmpty(ref)) {
            throw new ConfigurationException("No ref attribute provided for AppenderRef " + key);
        }
        final AppenderRefComponentBuilder appenderRefBuilder = builder.newAppenderRef(ref);
        final String level = Strings.trimToNull((String) properties.remove("level"));
        if (!Strings.isEmpty(level)) {
            appenderRefBuilder.addAttribute("level", level);
        }
        return addFiltersToComponent(appenderRefBuilder, properties);
    }

    private LoggerComponentBuilder createLogger(final String key, final Properties properties) {
        final String name = (String) properties.remove(CONFIG_NAME);
        final String location = (String) properties.remove("includeLocation");
        if (Strings.isEmpty(name)) {
            throw new ConfigurationException("No name attribute provided for Logger " + key);
        }
        final String level = Strings.trimToNull((String) properties.remove("level"));
        final String type = (String) properties.remove(CONFIG_TYPE);
        final LoggerComponentBuilder loggerBuilder;
        boolean includeLocation;
        if (type != null) {
            if (type.equalsIgnoreCase("asyncLogger")) {
                if (location != null) {
                    includeLocation = Boolean.parseBoolean(location);
                    loggerBuilder = builder.newAsyncLogger(name, level, includeLocation);
                } else {
                    loggerBuilder = builder.newAsyncLogger(name, level);
                }
            } else {
                throw new ConfigurationException("Unknown Logger type " + type + " for Logger " + name);
            }
        } else {
            if (location != null) {
                includeLocation = Boolean.parseBoolean(location);
                loggerBuilder = builder.newLogger(name, level, includeLocation);
            } else {
                loggerBuilder = builder.newLogger(name, level);
            }
        }
        addLoggersToComponent(loggerBuilder, properties);
        addFiltersToComponent(loggerBuilder, properties);
        final String additivity = (String) properties.remove("additivity");
        if (!Strings.isEmpty(additivity)) {
            loggerBuilder.addAttribute("additivity", additivity);
        }
        return loggerBuilder;
    }

    private RootLoggerComponentBuilder createRootLogger(final Properties properties) {
        final String level = Strings.trimToNull((String) properties.remove("level"));
        final String type = (String) properties.remove(CONFIG_TYPE);
        final String location = (String) properties.remove("includeLocation");
        final boolean includeLocation;
        final RootLoggerComponentBuilder loggerBuilder;
        if (type != null) {
            if (type.equalsIgnoreCase("asyncRoot")) {
                if (location != null) {
                    includeLocation = Boolean.parseBoolean(location);
                    loggerBuilder = builder.newAsyncRootLogger(level, includeLocation);
                } else {
                    loggerBuilder = builder.newAsyncRootLogger(level);
                }
            } else {
                throw new ConfigurationException("Unknown Logger type for root logger" + type);
            }
        } else {
            if (location != null) {
                includeLocation = Boolean.parseBoolean(location);
                loggerBuilder = builder.newRootLogger(level, includeLocation);
            } else {
                loggerBuilder = builder.newRootLogger(level);
            }
        }
        addLoggersToComponent(loggerBuilder, properties);
        return addFiltersToComponent(loggerBuilder, properties);
    }

    private LayoutComponentBuilder createLayout(final String appenderName, final Properties properties) {
        final String type = (String) properties.remove(CONFIG_TYPE);
        if (Strings.isEmpty(type)) {
            throw new ConfigurationException("No type attribute provided for Layout on Appender " + appenderName);
        }
        final LayoutComponentBuilder layoutBuilder = builder.newLayout(type);
        return processRemainingProperties(layoutBuilder, properties);
    }

    private static <B extends ComponentBuilder<B>> ComponentBuilder<B> createComponent(final ComponentBuilder<?> parent,
                                                                                       final String key,
                                                                                       final Properties properties) {
        final String name = (String) properties.remove(CONFIG_NAME);
        final String type = (String) properties.remove(CONFIG_TYPE);
        if (Strings.isEmpty(type)) {
            throw new ConfigurationException("No type attribute provided for component " + key);
        }
        final ComponentBuilder<B> componentBuilder = parent.getBuilder().newComponent(name, type);
        return processRemainingProperties(componentBuilder, properties);
    }

    private static <B extends ComponentBuilder<?>> B processRemainingProperties(final B builder,
                                                                                final Properties properties) {
        while (properties.size() > 0) {
            final String propertyName = properties.stringPropertyNames().iterator().next();
            final int index = propertyName.indexOf('.');
            if (index > 0) {
                final String prefix = propertyName.substring(0, index);
                final Properties componentProperties = PropertiesUtil.extractSubset(properties, prefix);
                builder.addComponent(createComponent(builder, prefix, componentProperties));
            } else {
                builder.addAttribute(propertyName, properties.getProperty(propertyName));
                properties.remove(propertyName);
            }
        }
        return builder;
    }

    private <B extends FilterableComponentBuilder<? extends ComponentBuilder<?>>> B addFiltersToComponent(
        final B componentBuilder, final Properties properties) {
        final Map<String, Properties> filters = PropertiesUtil.partitionOnCommonPrefixes(
            PropertiesUtil.extractSubset(properties, "filter"));
        for (final Map.Entry<String, Properties> entry : filters.entrySet()) {
            componentBuilder.add(createFilter(entry.getKey().trim(), entry.getValue()));
        }
        return componentBuilder;
    }

    private <B extends LoggableComponentBuilder<? extends ComponentBuilder<?>>> B addLoggersToComponent(
        final B loggerBuilder, final Properties properties) {
        final Map<String, Properties> appenderRefs = PropertiesUtil.partitionOnCommonPrefixes(
            PropertiesUtil.extractSubset(properties, "appenderRef"));
        for (final Map.Entry<String, Properties> entry : appenderRefs.entrySet()) {
            loggerBuilder.add(createAppenderRef(entry.getKey().trim(), entry.getValue()));
        }
        return loggerBuilder;
    }

    public PropertiesConfigurationBuilder setLoggerContext(final LoggerContext loggerContext) {
        this.loggerContext = loggerContext;
        return this;
    }

    public LoggerContext getLoggerContext() {
        return loggerContext;
    }
}
