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

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.time.SystemNanoClock;
import org.apache.logging.log4j.plugins.util.PluginManager;
import org.apache.logging.log4j.plugins.util.PluginType;
import org.apache.logging.log4j.status.StatusLogger;
import org.apache.logging.log4j.util.Strings;

/**
 * Most of the work of the {@link org.apache.logging.log4j.core.layout.PatternLayout} class is delegated to the
 * PatternParser class.
 * <p>
 * It is this class that parses conversion patterns and creates a chained list of {@link PatternConverter
 * PatternConverters}.
 */
public final class PatternParser {
    static final String DISABLE_ANSI = "disableAnsi";
    static final String NO_CONSOLE_NO_ANSI = "noConsoleNoAnsi";

    /**
     * Escape character for format specifier.
     */
    private static final char ESCAPE_CHAR = '%';

    /**
     * The states the parser can be in while parsing the pattern.
     */
    private enum ParserState {
        /**
         * Literal state.
         */
        LITERAL_STATE,

        /**
         * In converter name state.
         */
        CONVERTER_STATE,

        /**
         * Dot state.
         */
        DOT_STATE,

        /**
         * Min state.
         */
        MIN_STATE,

        /**
         * Max state.
         */
        MAX_STATE;
    }

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

    private static final int BUF_SIZE = 32;

    private static final int DECIMAL = 10;

    private final Configuration config;

    private final Map<String, Class<? extends PatternConverter>> converterRules;

    /**
     * Constructor.
     *
     * @param converterKey
     *            The type of converters that will be used.
     */
    public PatternParser(final String converterKey) {
        this(null, converterKey, null, null);
    }

    /**
     * Constructor.
     *
     * @param config
     *            The current Configuration.
     * @param converterKey
     *            The key to lookup the converters.
     * @param expected
     *            The expected base Class of each Converter.
     */
    public PatternParser(final Configuration config, final String converterKey, final Class<?> expected) {
        this(config, converterKey, expected, null);
    }

    /**
     * Constructor.
     *
     * @param config
     *            The current Configuration.
     * @param converterKey
     *            The key to lookup the converters.
     * @param expectedClass
     *            The expected base Class of each Converter.
     * @param filterClass
     *            Filter the returned plugins after calling the plugin manager.
     */
    public PatternParser(final Configuration config, final String converterKey, final Class<?> expectedClass,
            final Class<?> filterClass) {
        this.config = config;
        final PluginManager manager = new PluginManager(converterKey);
        manager.collectPlugins(config == null ? null : config.getPluginPackages());
        final Map<String, PluginType<?>> plugins = manager.getPlugins();
        final Map<String, Class<? extends PatternConverter>> converters = new LinkedHashMap<>();

        for (final PluginType<?> type : plugins.values()) {
            try {
                final Class<? extends PatternConverter> clazz = type.getPluginClass().asSubclass(PatternConverter.class);
                if (filterClass != null && !filterClass.isAssignableFrom(clazz)) {
                    continue;
                }
                final ConverterKeys keys = clazz.getAnnotation(ConverterKeys.class);
                if (keys != null) {
                    for (final String key : keys.value()) {
                        if (converters.containsKey(key)) {
                            LOGGER.warn("Converter key '{}' is already mapped to '{}'. " +
                                    "Sorry, Dave, I can't let you do that! Ignoring plugin [{}].",
                                key, converters.get(key), clazz);
                        } else {
                            converters.put(key, clazz);
                        }
                    }
                }
            } catch (final Exception ex) {
                LOGGER.error("Error processing plugin " + type.getElementName(), ex);
            }
        }
        converterRules = converters;
    }

    public List<PatternFormatter> parse(final String pattern) {
        return parse(pattern, false, false, false);
    }

    public List<PatternFormatter> parse(final String pattern, final boolean alwaysWriteExceptions,
                                        final boolean noConsoleNoAnsi) {
        return parse(pattern, alwaysWriteExceptions, false, noConsoleNoAnsi);
    }

    public List<PatternFormatter> parse(final String pattern, final boolean alwaysWriteExceptions,
           final boolean disableAnsi, final boolean noConsoleNoAnsi) {
        final List<PatternFormatter> list = new ArrayList<>();
        final List<PatternConverter> converters = new ArrayList<>();
        final List<FormattingInfo> fields = new ArrayList<>();

        parse(pattern, converters, fields, disableAnsi, noConsoleNoAnsi, true);

        final Iterator<FormattingInfo> fieldIter = fields.iterator();
        boolean handlesThrowable = false;

        for (final PatternConverter converter : converters) {
            if (converter instanceof NanoTimePatternConverter) {
                // LOG4J2-1074 Switch to actual clock if nanosecond timestamps are required in config.
                // LOG4J2-1248 set config nanoclock
                if (config != null) {
                    config.setNanoClock(new SystemNanoClock());
                }
            }
            LogEventPatternConverter pc;
            if (converter instanceof LogEventPatternConverter) {
                pc = (LogEventPatternConverter) converter;
                handlesThrowable |= pc.handlesThrowable();
            } else {
                pc = new LiteralPatternConverter(config, Strings.EMPTY, true);
            }

            FormattingInfo field;
            if (fieldIter.hasNext()) {
                field = fieldIter.next();
            } else {
                field = FormattingInfo.getDefault();
            }
            list.add(new PatternFormatter(pc, field));
        }
        if (alwaysWriteExceptions && !handlesThrowable) {
            final LogEventPatternConverter pc = ExtendedThrowablePatternConverter.newInstance(config, null);
            list.add(new PatternFormatter(pc, FormattingInfo.getDefault()));
        }
        return list;
    }

    /**
     * Extracts the converter identifier found at the given start position.
     * <p>
     * After this function returns, the variable i will point to the first char after the end of the converter
     * identifier.
     * </p>
     * <p>
     * If i points to a char which is not a character acceptable at the start of a unicode identifier, the value null is
     * returned.
     * </p>
     *
     * @param lastChar
     *        last processed character.
     * @param pattern
     *        format string.
     * @param start
     *        current index into pattern format.
     * @param convBuf
     *        buffer to receive conversion specifier.
     * @param currentLiteral
     *        literal to be output in case format specifier in unrecognized.
     * @return position in pattern after converter.
     */
    private static int extractConverter(final char lastChar, final String pattern, final int start,
            final StringBuilder convBuf, final StringBuilder currentLiteral) {
        int i = start;
        convBuf.setLength(0);

        // When this method is called, lastChar points to the first character of the
        // conversion word. For example:
        // For "%hello" lastChar = 'h'
        // For "%-5hello" lastChar = 'h'
        // System.out.println("lastchar is "+lastChar);
        if (!Character.isUnicodeIdentifierStart(lastChar)) {
            return i;
        }

        convBuf.append(lastChar);

        while (i < pattern.length() && Character.isUnicodeIdentifierPart(pattern.charAt(i))) {
            convBuf.append(pattern.charAt(i));
            currentLiteral.append(pattern.charAt(i));
            i++;
        }

        return i;
    }

    /**
     * Extract options.
     *
     * @param pattern
     *            conversion pattern.
     * @param start
     *            start of options.
     * @param options
     *            array to receive extracted options
     * @return position in pattern after options.
     */
    private static int extractOptions(final String pattern, final int start, final List<String> options) {
        int i = start;
        while (i < pattern.length() && pattern.charAt(i) == '{') {
            i++; // skip opening "{"
            final int begin = i; // position of first real char
            int depth = 1; // already inside one level
            while (depth > 0 && i < pattern.length()) {
                char c = pattern.charAt(i);
                if (c == '{') {
                    depth++;
                } else if (c == '}') {
                    depth--;
                    // TODO(?) maybe escaping of { and } with \ or %
                }
                i++;
            } // while

            if (depth > 0) { // option not closed, continue with pattern after closing bracket
                i = pattern.lastIndexOf('}');
                if (i == -1 || i < start) {
                    // if no closing bracket could be found or there is no closing bracket behind the starting
                    // character of our parsing process continue parsing after the first opening bracket
                    return begin;
                }
                return i + 1;
            }

            options.add(pattern.substring(begin, i - 1));
        } // while

        return i;
    }

    /**
     * Parse a format specifier.
     *
     * @param pattern
     *            pattern to parse.
     * @param patternConverters
     *            list to receive pattern converters.
     * @param formattingInfos
     *            list to receive field specifiers corresponding to pattern converters.
     * @param noConsoleNoAnsi
     *            do not do not output ANSI escape codes if {@link System#console()}
     * @param convertBackslashes if {@code true}, backslash characters are treated as escape characters and character
     *            sequences like "\" followed by "t" (backslash+t) are converted to special characters like '\t' (tab).
     */
    public void parse(final String pattern, final List<PatternConverter> patternConverters,
                      final List<FormattingInfo> formattingInfos, final boolean noConsoleNoAnsi,
                      final boolean convertBackslashes) {
        parse(pattern, patternConverters, formattingInfos, false, noConsoleNoAnsi, convertBackslashes);
    }

    /**
     * Parse a format specifier.
     *
     * @param pattern
     *            pattern to parse.
     * @param patternConverters
     *            list to receive pattern converters.
     * @param formattingInfos
     *            list to receive field specifiers corresponding to pattern converters.
     * @param disableAnsi
     *            do not output ANSI escape codes
     * @param noConsoleNoAnsi
     *            do not do not output ANSI escape codes if {@link System#console()}
     * @param convertBackslashes if {@code true}, backslash characters are treated as escape characters and character
     *            sequences like "\" followed by "t" (backslash+t) are converted to special characters like '\t' (tab).
     */
    public void parse(final String pattern, final List<PatternConverter> patternConverters,
            final List<FormattingInfo> formattingInfos, final boolean disableAnsi,
            final boolean noConsoleNoAnsi, final boolean convertBackslashes) {
        Objects.requireNonNull(pattern, "pattern");

        final StringBuilder currentLiteral = new StringBuilder(BUF_SIZE);

        final int patternLength = pattern.length();
        ParserState state = ParserState.LITERAL_STATE;
        char c;
        int i = 0;
        FormattingInfo formattingInfo = FormattingInfo.getDefault();

        while (i < patternLength) {
            c = pattern.charAt(i++);

            switch (state) {
            case LITERAL_STATE:

                // In literal state, the last char is always a literal.
                if (i == patternLength) {
                    currentLiteral.append(c);

                    continue;
                }

                if (c == ESCAPE_CHAR) {
                    // peek at the next char.
                    switch (pattern.charAt(i)) {
                    case ESCAPE_CHAR:
                        currentLiteral.append(c);
                        i++; // move pointer

                        break;

                    default:

                        if (currentLiteral.length() != 0) {
                            patternConverters.add(new LiteralPatternConverter(config, currentLiteral.toString(),
                                    convertBackslashes));
                            formattingInfos.add(FormattingInfo.getDefault());
                        }

                        currentLiteral.setLength(0);
                        currentLiteral.append(c); // append %
                        state = ParserState.CONVERTER_STATE;
                        formattingInfo = FormattingInfo.getDefault();
                    }
                } else {
                    currentLiteral.append(c);
                }

                break;

            case CONVERTER_STATE:
                currentLiteral.append(c);

                switch (c) {
                case '0':
                    // a '0' directly after the % sign indicates zero-padding
                    formattingInfo = new FormattingInfo(formattingInfo.isLeftAligned(), formattingInfo.getMinLength(),
                            formattingInfo.getMaxLength(), formattingInfo.isLeftTruncate(), true);
                    break;

                case '-':
                    formattingInfo = new FormattingInfo(true, formattingInfo.getMinLength(),
                            formattingInfo.getMaxLength(), formattingInfo.isLeftTruncate(), formattingInfo.isZeroPad());
                    break;

                case '.':
                    state = ParserState.DOT_STATE;
                    break;

                default:

                    if (c >= '0' && c <= '9') {
                        formattingInfo = new FormattingInfo(formattingInfo.isLeftAligned(), c - '0',
                                formattingInfo.getMaxLength(), formattingInfo.isLeftTruncate(), formattingInfo.isZeroPad());
                        state = ParserState.MIN_STATE;
                    } else {
                        i = finalizeConverter(c, pattern, i, currentLiteral, formattingInfo, converterRules,
                                patternConverters, formattingInfos, disableAnsi, noConsoleNoAnsi, convertBackslashes);

                        // Next pattern is assumed to be a literal.
                        state = ParserState.LITERAL_STATE;
                        formattingInfo = FormattingInfo.getDefault();
                        currentLiteral.setLength(0);
                    }
                } // switch

                break;

            case MIN_STATE:
                currentLiteral.append(c);

                if (c >= '0' && c <= '9') {
                    // Multiply the existing value and add the value of the number just encountered.
                    formattingInfo = new FormattingInfo(formattingInfo.isLeftAligned(), formattingInfo.getMinLength()
                            * DECIMAL + c - '0', formattingInfo.getMaxLength(), formattingInfo.isLeftTruncate(), formattingInfo.isZeroPad());
                } else if (c == '.') {
                    state = ParserState.DOT_STATE;
                } else {
                    i = finalizeConverter(c, pattern, i, currentLiteral, formattingInfo, converterRules,
                            patternConverters, formattingInfos, disableAnsi, noConsoleNoAnsi, convertBackslashes);
                    state = ParserState.LITERAL_STATE;
                    formattingInfo = FormattingInfo.getDefault();
                    currentLiteral.setLength(0);
                }

                break;

            case DOT_STATE:
                currentLiteral.append(c);
                switch (c) {
                case '-':
                    formattingInfo = new FormattingInfo(formattingInfo.isLeftAligned(), formattingInfo.getMinLength(),
                            formattingInfo.getMaxLength(),false, formattingInfo.isZeroPad());
                    break;

                default:

	                if (c >= '0' && c <= '9') {
	                    formattingInfo = new FormattingInfo(formattingInfo.isLeftAligned(), formattingInfo.getMinLength(),
	                            c - '0', formattingInfo.isLeftTruncate(), formattingInfo.isZeroPad());
	                    state = ParserState.MAX_STATE;
	                } else {
	                    LOGGER.error("Error occurred in position " + i + ".\n Was expecting digit, instead got char \"" + c
	                            + "\".");

	                    state = ParserState.LITERAL_STATE;
	                }
                }

                break;

            case MAX_STATE:
                currentLiteral.append(c);

                if (c >= '0' && c <= '9') {
                    // Multiply the existing value and add the value of the number just encountered.
                    formattingInfo = new FormattingInfo(formattingInfo.isLeftAligned(), formattingInfo.getMinLength(),
                            formattingInfo.getMaxLength() * DECIMAL + c - '0', formattingInfo.isLeftTruncate(), formattingInfo.isZeroPad());
                } else {
                    i = finalizeConverter(c, pattern, i, currentLiteral, formattingInfo, converterRules,
                            patternConverters, formattingInfos, disableAnsi, noConsoleNoAnsi, convertBackslashes);
                    state = ParserState.LITERAL_STATE;
                    formattingInfo = FormattingInfo.getDefault();
                    currentLiteral.setLength(0);
                }

                break;
            } // switch
        }

        // while
        if (currentLiteral.length() != 0) {
            patternConverters.add(new LiteralPatternConverter(config, currentLiteral.toString(), convertBackslashes));
            formattingInfos.add(FormattingInfo.getDefault());
        }
    }

    /**
     * Creates a new PatternConverter.
     *
     * @param converterId
     *            converterId.
     * @param currentLiteral
     *            literal to be used if converter is unrecognized or following converter if converterId contains extra
     *            characters.
     * @param rules
     *            map of stock pattern converters keyed by format specifier.
     * @param options
     *            converter options.
     * @param disableAnsi
     *            do not output ANSI escape codes
     * @param noConsoleNoAnsi
     *            do not do not output ANSI escape codes if {@link System#console()}
     * @return converter or null.
     */
    private PatternConverter createConverter(final String converterId, final StringBuilder currentLiteral,
            final Map<String, Class<? extends PatternConverter>> rules, final List<String> options, final boolean disableAnsi,
            final boolean noConsoleNoAnsi) {
        String converterName = converterId;
        Class<? extends PatternConverter> converterClass = null;

        if (rules == null) {
            LOGGER.error("Null rules for [" + converterId + ']');
            return null;
        }
        for (int i = converterId.length(); i > 0 && converterClass == null; i--) {
            converterName = converterName.substring(0, i);
            converterClass = rules.get(converterName);
        }

        if (converterClass == null) {
            LOGGER.error("Unrecognized format specifier [" + converterId + ']');
            return null;
        }

        if (AnsiConverter.class.isAssignableFrom(converterClass)) {
            options.add(DISABLE_ANSI + '=' + disableAnsi);
            options.add(NO_CONSOLE_NO_ANSI + '=' + noConsoleNoAnsi);
        }
        // Work around the regression bug in Class.getDeclaredMethods() in Oracle Java in version > 1.6.0_17:
        // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6815786
        final Method[] methods = converterClass.getDeclaredMethods();
        Method newInstanceMethod = null;
        for (final Method method : methods) {
            if (Modifier.isStatic(method.getModifiers())
                    && method.getDeclaringClass().equals(converterClass)
                    && method.getName().equals("newInstance")
                    && areValidNewInstanceParameters(method.getParameterTypes())) {
                if (newInstanceMethod == null) {
                    newInstanceMethod = method;
                } else if (method.getReturnType().equals(newInstanceMethod.getReturnType())) {
                    LOGGER.error("Class " + converterClass + " cannot contain multiple static newInstance methods");
                    return null;
                }
            }
        }
        if (newInstanceMethod == null) {
            LOGGER.error("Class " + converterClass + " does not contain a static newInstance method");
            return null;
        }

        final Class<?>[] parmTypes = newInstanceMethod.getParameterTypes();
        final Object[] parms = parmTypes.length > 0 ? new Object[parmTypes.length] : null;

        if (parms != null) {
            int i = 0;
            boolean errors = false;
            for (final Class<?> clazz : parmTypes) {
                if (clazz.isArray() && clazz.getName().equals("[Ljava.lang.String;")) {
                    final String[] optionsArray = options.toArray(new String[options.size()]);
                    parms[i] = optionsArray;
                } else if (clazz.isAssignableFrom(Configuration.class)) {
                    parms[i] = config;
                } else {
                    LOGGER.error("Unknown parameter type " + clazz.getName() + " for static newInstance method of "
                            + converterClass.getName());
                    errors = true;
                }
                ++i;
            }
            if (errors) {
                return null;
            }
        }

        try {
            final Object newObj = newInstanceMethod.invoke(null, parms);

            if (newObj instanceof PatternConverter) {
                currentLiteral.delete(0, currentLiteral.length() - (converterId.length() - converterName.length()));

                return (PatternConverter) newObj;
            }
            LOGGER.warn("Class {} does not extend PatternConverter.", converterClass.getName());
        } catch (final Exception ex) {
            LOGGER.error("Error creating converter for " + converterId, ex);
        }

        return null;
    }

    /** LOG4J2-2564: Returns true if all method parameters are valid for injection. */
    private static boolean areValidNewInstanceParameters(Class<?>[] parameterTypes) {
        for (Class<?> clazz : parameterTypes) {
            if (!clazz.isAssignableFrom(Configuration.class)
                    && !(clazz.isArray() && "[Ljava.lang.String;".equals(clazz.getName()))) {
                return false;
            }
        }
        return true;
    }

    /**
     * Processes a format specifier sequence.
     *
     * @param c
     *            initial character of format specifier.
     * @param pattern
     *            conversion pattern
     * @param start
     *            current position in conversion pattern.
     * @param currentLiteral
     *            current literal.
     * @param formattingInfo
     *            current field specifier.
     * @param rules
     *            map of stock pattern converters keyed by format specifier.
     * @param patternConverters
     *            list to receive parsed pattern converter.
     * @param formattingInfos
     *            list to receive corresponding field specifier.
     * @param disableAnsi
     *            do not output ANSI escape codes
     * @param noConsoleNoAnsi
     *            do not do not output ANSI escape codes if {@link System#console()}
     * @param convertBackslashes if {@code true}, backslash characters are treated as escape characters and character
     *            sequences like "\" followed by "t" (backslash+t) are converted to special characters like '\t' (tab).
     * @return position after format specifier sequence.
     */
    private int finalizeConverter(final char c, final String pattern, final int start,
            final StringBuilder currentLiteral, final FormattingInfo formattingInfo,
            final Map<String, Class<? extends PatternConverter>> rules, final List<PatternConverter> patternConverters,
            final List<FormattingInfo> formattingInfos, final boolean disableAnsi, final boolean noConsoleNoAnsi,
            final boolean convertBackslashes) {
        int i = start;
        final StringBuilder convBuf = new StringBuilder();
        i = extractConverter(c, pattern, i, convBuf, currentLiteral);

        final String converterId = convBuf.toString();

        final List<String> options = new ArrayList<>();
        i = extractOptions(pattern, i, options);

        final PatternConverter pc = createConverter(converterId, currentLiteral, rules, options, disableAnsi,
            noConsoleNoAnsi);

        if (pc == null) {
            StringBuilder msg;

            if (Strings.isEmpty(converterId)) {
                msg = new StringBuilder("Empty conversion specifier starting at position ");
            } else {
                msg = new StringBuilder("Unrecognized conversion specifier [");
                msg.append(converterId);
                msg.append("] starting at position ");
            }

            msg.append(Integer.toString(i));
            msg.append(" in conversion pattern.");

            LOGGER.error(msg.toString());

            patternConverters.add(new LiteralPatternConverter(config, currentLiteral.toString(), convertBackslashes));
            formattingInfos.add(FormattingInfo.getDefault());
        } else {
            patternConverters.add(pc);
            formattingInfos.add(formattingInfo);

            if (currentLiteral.length() > 0) {
                patternConverters
                        .add(new LiteralPatternConverter(config, currentLiteral.toString(), convertBackslashes));
                formattingInfos.add(FormattingInfo.getDefault());
            }
        }

        currentLiteral.setLength(0);

        return i;
    }
}
