/*
 * 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.core.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 Appender " + 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;
    }
}
