package usda.weru.util;

import java.io.File;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.ConfigurationFactory;
import org.apache.logging.log4j.core.config.ConfigurationSource;
import org.apache.logging.log4j.core.config.LoggerConfig;
import org.apache.logging.log4j.core.config.Order;
import org.apache.logging.log4j.core.config.builder.api.AppenderComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
import org.apache.logging.log4j.core.config.builder.api.FilterComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.LayoutComponentBuilder;
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.impl.BuiltConfiguration;
import org.apache.logging.log4j.core.config.plugins.Plugin;

/**
 *
 * @author mark
 */
@Plugin(name="Log4jWepsConfigurationFactory", category="ConfigurationFactory")
@Order(100)
public class Log4jWepsConfigurationFactory extends ConfigurationFactory {
    
    public static final String[] SUFFIXES = new String[] {".xml", "*"};

    protected static Log4jWepsConfigurationFactory currentFactory = null;

//    BuiltConfiguration builtConfigSave;
//    AppenderComponentBuilder fileAppenderSave;

    public Log4jWepsConfigurationFactory() {
        super();
        currentFactory = this;

    }

    public static Log4jWepsConfigurationFactory getCurrentFactory() {
        return currentFactory;
    }


    /**
     * Return the Configuration.
     * @param loggerContext
     * @return The Configuration.
     */
    @Override
     public Configuration getConfiguration(LoggerContext loggerContext, ConfigurationSource source) {
        ConfigurationBuilder<BuiltConfiguration> builder = getConfigBuilder ("log/wepsInitial2.log");
        return builder.build();

    }

ConfigurationBuilder<BuiltConfiguration> getConfigBuilder (String logFileName) {
        ConfigurationBuilder<BuiltConfiguration> builder = newConfigurationBuilder();

        // The output pattern for the file appender
        LayoutComponentBuilder consolePattern 
          = builder.newLayout("PatternLayout");
        consolePattern.addAttribute("pattern", "%-5level %logger{36}:%L %msg%n");

        // The level filter for the console appender
        FilterComponentBuilder consoleLevelFilter = builder.newFilter(
          "ThresholdFilter", 
          Filter.Result.ACCEPT,
          Filter.Result.DENY);  
        consoleLevelFilter.addAttribute("level", Level.WARN);

//        FilterComponentBuilder netcdfFilter = builder.newFilter(
//          "RegexFilter", 
//          Filter.Result.DENY,
//          Filter.Result.NEUTRAL);  
////        netcdfFilter.addAttribute("regex", ".*Nodechild.*");
//        netcdfFilter.addAttribute("regex", ".*netcdf.*");
////        netcdfFilter.addAttribute("useRawMsg", true);
//
//        ComponentBuilder consoleCompositeFilter = builder.newComponent("filters");
//        consoleCompositeFilter.addComponent(consoleLevelFilter);
//        consoleCompositeFilter.addComponent(netcdfFilter);

        // The console appender for the root logger
        AppenderComponentBuilder console 
          = builder.newAppender("stdout", "Console"); 
        console.add(consolePattern);
//        console.addComponent(consoleCompositeFilter);
        console.addComponent(consoleLevelFilter);
        builder.add(console);

        // The output pattern for the file appender
        LayoutComponentBuilder filePattern 
          = builder.newLayout("PatternLayout");
//        filePattern.addAttribute("pattern", "%d{HH:mm:ss.SSS} %-5level %logger{36}:%L %msg%n");
        filePattern.addAttribute("pattern", "%d{HH:mm:ss.SSS} %-5level %class{36}:%L %msg%n");

        // The level filter for the file appender
        FilterComponentBuilder fileLevelFilter = builder.newFilter(
          "ThresholdFilter", 
          Filter.Result.ACCEPT,
          Filter.Result.DENY);  
        fileLevelFilter.addAttribute("level", Level.INFO);

        // The file appender for the root logger
        AppenderComponentBuilder file = builder.newAppender("WepsLogFile", "File"); 
//        file.addAttribute("fileName", "log/wepsInitial.log");
        file.addAttribute("fileName", logFileName);
        file.addAttribute("append", false);
        file.add(filePattern);
        file.add(fileLevelFilter);
        builder.add(file);


        // The root logger
        RootLoggerComponentBuilder rootLogger 
          = builder.newRootLogger(Level.ALL);
        rootLogger.add(builder.newAppenderRef("stdout"));
        rootLogger.add(builder.newAppenderRef("WepsLogFile"));
        builder.add(rootLogger);


        // Used for debugging httpChildLogger below
//        AppenderComponentBuilder junkfile = builder.newAppender("WepsJunkFile", "File"); 
        //junkfile.addAttribute("fileName", "log/wepsJunk.log");
//        String junkFileName = new File(new File(logFileName).getParentFile(),"wepsJunk.log").getPath();
//        junkfile.addAttribute("fileName", junkFileName);
//        junkfile.addAttribute("append", false);
        //junkfile.add(filePattern);
//        builder.add(junkfile);

        // Everything from org.apache.http will get sent here
        // It posts a ton of logging that clutters up the logs
        // remove the WepsJunkFile appender to makeit into a simple bit-bucket.
        LoggerComponentBuilder httpChildLogger = builder.newLogger("org.apache.http", Level.ALL);
        httpChildLogger.addAttribute("additivity", false);
//        httpChildLogger.add(builder.newAppenderRef("WepsJunkFile")); DNA
        builder.add(httpChildLogger);

        // Everything from org.apache.commons.digester will get sent here
        // It posts a ton of logging that clutters up the logs
        // remove the WepsJunkFile appender to makeit into a simple bit-bucket.
        LoggerComponentBuilder digesterChildLogger = builder.newLogger("org.apache.commons.digester", Level.ALL);
        digesterChildLogger.addAttribute("additivity", false);
//        digesterChildLogger.add(builder.newAppenderRef("WepsJunkFile"));  DNA
        builder.add(digesterChildLogger);

        // Everything from net.sf.jasperreports will get sent here
        // It posts a ton of logging that clutters up the logs
        // remove the WepsJunkFile appender to makeit into a simple bit-bucket.
        LoggerComponentBuilder jasperChildLogger = builder.newLogger("net.sf.jasperreports", Level.ALL);
        jasperChildLogger.addAttribute("additivity", false);
//        jasperChildLogger.add(builder.newAppenderRef("WepsJunkFile"));
        builder.add(jasperChildLogger);

        // Everything from org.geotools.tile will get sent here
        // It posts a ton of logging that clutters up the logs
        // remove the WepsJunkFile appender to makeit into a simple bit-bucket.
        LoggerComponentBuilder geo1ChildLogger = builder.newLogger("org.geotools.tile", Level.ALL);
        geo1ChildLogger.addAttribute("additivity", false);
//        geo1ChildLogger.add(builder.newAppenderRef("WepsJunkFile"));
        builder.add(geo1ChildLogger);

        // Everything from org.geotools.util will get sent here
        // It posts a ton of logging that clutters up the logs
        // remove the WepsJunkFile appender to makeit into a simple bit-bucket.
        LoggerComponentBuilder geo2ChildLogger = builder.newLogger("org.geotools.util", Level.ALL);
        geo2ChildLogger.addAttribute("additivity", false);
//        geo2ChildLogger.add(builder.newAppenderRef("WepsJunkFile"));
        builder.add(geo2ChildLogger);

        // Everything from org.geotools.data will get sent here
        // It posts a ton of logging that clutters up the logs
        // remove the WepsJunkFile appender to makeit into a simple bit-bucket.
        LoggerComponentBuilder geo3ChildLogger = builder.newLogger("org.geotools.data", Level.ALL);
        geo3ChildLogger.addAttribute("additivity", false);
//        geo3ChildLogger.add(builder.newAppenderRef("WepsJunkFile"));
        builder.add(geo3ChildLogger);


//        try {
//            builder.writeXmlConfiguration(System.out);
//        } catch (IOException e) {
//        }

        return builder;
    }
 
    /**
     * Returns the file suffixes for XML files.
     * @return An array of File extensions.
     */
    @Override
    public String[] getSupportedTypes() {
        return SUFFIXES;
    }

    public void setLoggingOff () {

        final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
        final Configuration config = ctx.getConfiguration();
        LoggerConfig loggerConfig = config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME);
        loggerConfig.setLevel(org.apache.logging.log4j.Level.OFF);

        ctx.updateLoggers();
    }

    public void setLoggingOn () {

        final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
        final Configuration config = ctx.getConfiguration();
        LoggerConfig loggerConfig = config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME);
        loggerConfig.setLevel(org.apache.logging.log4j.Level.ALL);

        ctx.updateLoggers();
    }

    public void updateLogFileName (String newName) {

        final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
        ConfigurationBuilder<BuiltConfiguration> builder2 = getConfigBuilder (newName);
        ctx.setConfiguration(builder2.build());
    }
}
