package ru.yandex.qe.logging;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.core.joran.spi.JoranException;
import ch.qos.logback.core.status.InfoStatus;
import org.slf4j.LoggerFactory;

/**
 * Established by terry
 * on 12.01.14.
 */
public class LoggingInitializer {
    private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(LoggingInitializer.class);

    private static final String QE_LOGGER_CONFIG_NAME = "qe-logback";
    private static final String QE_CUSTOM_LOGGER_LOCATION = "logging/qe-logback.xml";
    private static final String QE_DEFAULT_LOGGER_LOCATION = "qe-logback.xml";

    public static void initialize() {
        final LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
        if (!QE_LOGGER_CONFIG_NAME.equals(context.getName())) {
            try {
                tryInitializeCustomLogback(context, QE_CUSTOM_LOGGER_LOCATION);
            } catch (IOException e) {
                System.err.println(QE_CUSTOM_LOGGER_LOCATION + " failed:" + e.toString() + ", falling through");
            }
            try {
                tryInitializeCustomLogback(context, QE_DEFAULT_LOGGER_LOCATION);
            } catch (IOException e) {
                System.err.println(QE_DEFAULT_LOGGER_LOCATION + " failed:" + e.toString() + ", falling through");
            }
        }
        tryInitializeQloudLogging(context);
    }

    private static void tryInitializeQloudLogging(LoggerContext context) {
        final Logger logger = context.getLogger(Logger.ROOT_LOGGER_NAME);

        final Map<String, String> env = System.getenv();
        if (env.containsKey("QLOUD_LOGGER_LEVEL")) {
            final Level currentLevel = logger.getLevel();
            final Level newLevel = Level.toLevel(env.get("QLOUD_LOGGER_LEVEL"), currentLevel);

            LOG.info("QLOUD: Overriding log level to {}. Was: {}", newLevel, currentLevel);
            logger.setLevel(newLevel);
        }
    }

    private static boolean tryInitializeCustomLogback(LoggerContext context, final String loggerLocation) throws IOException {
        final Enumeration<URL> logbackConfigsEnumeration;
        final List<URL> logbackLocations = new ArrayList<>();
        logbackConfigsEnumeration = LoggingInitializer.class.getClassLoader().getResources(loggerLocation);
        while (logbackConfigsEnumeration.hasMoreElements()) {
            logbackLocations.add(logbackConfigsEnumeration.nextElement());
        }
        if (logbackLocations.size() != 1) {
            System.err.println(String.format("Expected one %s but found %s: %s, ignoring", loggerLocation, logbackLocations.size(), logbackLocations));
            return false;
        }
        final InputStream customLogback = logbackLocations.get(0).openStream();
        if (customLogback != null) {
            context.getStatusManager().add(new InfoStatus(
                    String.format("Apply custom logback.xml %s", QE_CUSTOM_LOGGER_LOCATION), new LoggingInitializer()));
            final JoranConfigurator joranConfigurator = new JoranConfigurator();
            joranConfigurator.setContext(context);
            try {
                context.reset();
                joranConfigurator.doConfigure(customLogback);
                return true;
            } catch (JoranException e) {
                System.err.println("fail to init custom logback");
                e.printStackTrace(System.err);
            } finally {
                try {
                    customLogback.close();
                } catch (IOException e) {
                    // ignore
                }
            }
        }
        return false;
    }

}
