/*
 * 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.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.List;

import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.layout.PatternLayout;
import org.apache.logging.log4j.util.PerformanceSensitive;

/**
 * Style pattern converter. Adds ANSI color styling to the result of the enclosed pattern.
 */
public abstract class AbstractStyleNameConverter extends LogEventPatternConverter /*TODO: implements AnsiConverter*/ {

    private final List<PatternFormatter> formatters;

    private final String style;

    /**
     * Constructs the converter.
     *
     * @param formatters The PatternFormatters to generate the text to manipulate.
     * @param styling The styling that should encapsulate the pattern.
     */
    protected AbstractStyleNameConverter(final String name, final List<PatternFormatter> formatters,
                                         final String styling) {
        super(name, "style");
        this.formatters = formatters;
        this.style = styling;
    }

    /**
     * Black style pattern converter. Adds ANSI color styling to the result of the enclosed pattern.
     */
    @Plugin(name = Black.NAME, category = "Converter")
    @ConverterKeys(Black.NAME)
    public static final class Black extends AbstractStyleNameConverter {

        /** Black */
        protected static final String NAME = "black";

        /**
         * Constructs the converter. This constructor must be public.
         *
         * @param formatters The PatternFormatters to generate the text to manipulate.
         * @param styling The styling that should encapsulate the pattern.
         */
        public Black(final List<PatternFormatter> formatters, final String styling) {
            super(NAME, formatters, styling);
        }

        /**
         * Gets an instance of the class (called via reflection).
         *
         * @param config The current Configuration.
         * @param options The pattern options, may be null. If the first element is "short", only the first line of the
         *            throwable will be formatted.
         * @return new instance of class or null
         */
        public static Black newInstance(final Configuration config, final String[] options) {
            return newInstance(Black.class, NAME, config, options);
        }
    }

    /**
     * Blue style pattern converter. Adds ANSI color styling to the result of the enclosed pattern.
     */
    @Plugin(name = Blue.NAME, category = "Converter")
    @ConverterKeys(Blue.NAME)
    public static final class Blue extends AbstractStyleNameConverter {

        /** Blue */
        protected static final String NAME = "blue";

        /**
         * Constructs the converter. This constructor must be public.
         *
         * @param formatters The PatternFormatters to generate the text to manipulate.
         * @param styling The styling that should encapsulate the pattern.
         */
        public Blue(final List<PatternFormatter> formatters, final String styling) {
            super(NAME, formatters, styling);
        }

        /**
         * Gets an instance of the class (called via reflection).
         *
         * @param config The current Configuration.
         * @param options The pattern options, may be null. If the first element is "short", only the first line of the
         *                throwable will be formatted.
         * @return new instance of class or null
         */
        public static Blue newInstance(final Configuration config, final String[] options) {
            return newInstance(Blue.class, NAME, config, options);
        }
    }

    /**
     * Cyan style pattern converter. Adds ANSI color styling to the result of the enclosed pattern.
     */
    @Plugin(name = Cyan.NAME, category = "Converter")
    @ConverterKeys(Cyan.NAME)
    public static final class Cyan extends AbstractStyleNameConverter {

        /** Cyan */
        protected static final String NAME = "cyan";

        /**
         * Constructs the converter. This constructor must be public.
         *
         * @param formatters The PatternFormatters to generate the text to manipulate.
         * @param styling The styling that should encapsulate the pattern.
         */
        public Cyan(final List<PatternFormatter> formatters, final String styling) {
            super(NAME, formatters, styling);
        }

        /**
         * Gets an instance of the class (called via reflection).
         *
         * @param config The current Configuration.
         * @param options The pattern options, may be null. If the first element is "short", only the first line of the
         *                throwable will be formatted.
         * @return new instance of class or null
         */
        public static Cyan newInstance(final Configuration config, final String[] options) {
            return newInstance(Cyan.class, NAME, config, options);
        }
    }

    /**
     * Green style pattern converter. Adds ANSI color styling to the result of the enclosed pattern.
     */
    @Plugin(name = Green.NAME, category = "Converter")
    @ConverterKeys(Green.NAME)
    public static final class Green extends AbstractStyleNameConverter {

        /** Green */
        protected static final String NAME = "green";

        /**
         * Constructs the converter. This constructor must be public.
         *
         * @param formatters The PatternFormatters to generate the text to manipulate.
         * @param styling The styling that should encapsulate the pattern.
         */
        public Green(final List<PatternFormatter> formatters, final String styling) {
            super(NAME, formatters, styling);
        }

        /**
         * Gets an instance of the class (called via reflection).
         *
         * @param config The current Configuration.
         * @param options The pattern options, may be null. If the first element is "short", only the first line of the
         *                throwable will be formatted.
         * @return new instance of class or null
         */
        public static Green newInstance(final Configuration config, final String[] options) {
            return newInstance(Green.class, NAME, config, options);
        }
    }

    /**
     * Magenta style pattern converter. Adds ANSI color styling to the result of the enclosed pattern.
     */
    @Plugin(name = Magenta.NAME, category = "Converter")
    @ConverterKeys(Magenta.NAME)
    public static final class Magenta extends AbstractStyleNameConverter {

        /** Magenta */
        protected static final String NAME = "magenta";

        /**
         * Constructs the converter. This constructor must be public.
         *
         * @param formatters The PatternFormatters to generate the text to manipulate.
         * @param styling The styling that should encapsulate the pattern.
         */
        public Magenta(final List<PatternFormatter> formatters, final String styling) {
            super(NAME, formatters, styling);
        }

        /**
         * Gets an instance of the class (called via reflection).
         *
         * @param config The current Configuration.
         * @param options The pattern options, may be null. If the first element is "short", only the first line of the
         *                throwable will be formatted.
         * @return new instance of class or null
         */
        public static Magenta newInstance(final Configuration config, final String[] options) {
            return newInstance(Magenta.class, NAME, config, options);
        }
    }

    /**
     * Red style pattern converter. Adds ANSI color styling to the result of the enclosed pattern.
     */
    @Plugin(name = Red.NAME, category = "Converter")
    @ConverterKeys(Red.NAME)
    public static final class Red extends AbstractStyleNameConverter {

        /** Red */
        protected static final String NAME = "red";

        /**
         * Constructs the converter. This constructor must be public.
         *
         * @param formatters The PatternFormatters to generate the text to manipulate.
         * @param styling The styling that should encapsulate the pattern.
         */
        public Red(final List<PatternFormatter> formatters, final String styling) {
            super(NAME, formatters, styling);
        }

        /**
         * Gets an instance of the class (called via reflection).
         *
         * @param config The current Configuration.
         * @param options The pattern options, may be null. If the first element is "short", only the first line of the
         *                throwable will be formatted.
         * @return new instance of class or null
         */
        public static Red newInstance(final Configuration config, final String[] options) {
            return newInstance(Red.class, NAME, config, options);
        }
    }

    /**
     * White style pattern converter. Adds ANSI color styling to the result of the enclosed pattern.
     */
    @Plugin(name = White.NAME, category = "Converter")
    @ConverterKeys(White.NAME)
    public static final class White extends AbstractStyleNameConverter {

        /** White */
        protected static final String NAME = "white";

        /**
         * Constructs the converter. This constructor must be public.
         *
         * @param formatters The PatternFormatters to generate the text to manipulate.
         * @param styling The styling that should encapsulate the pattern.
         */
        public White(final List<PatternFormatter> formatters, final String styling) {
            super(NAME, formatters, styling);
        }

        /**
         * Gets an instance of the class (called via reflection).
         *
         * @param config The current Configuration.
         * @param options The pattern options, may be null. If the first element is "short", only the first line of the
         *                throwable will be formatted.
         * @return new instance of class or null
         */
        public static White newInstance(final Configuration config, final String[] options) {
            return newInstance(White.class, NAME, config, options);
        }
    }

    /**
     * Yellow style pattern converter. Adds ANSI color styling to the result of the enclosed pattern.
     */
    @Plugin(name = Yellow.NAME, category = "Converter")
    @ConverterKeys(Yellow.NAME)
    public static final class Yellow extends AbstractStyleNameConverter {

        /** Yellow */
        protected static final String NAME = "yellow";

        /**
         * Constructs the converter. This constructor must be public.
         *
         * @param formatters The PatternFormatters to generate the text to manipulate.
         * @param styling The styling that should encapsulate the pattern.
         */
        public Yellow(final List<PatternFormatter> formatters, final String styling) {
            super(NAME, formatters, styling);
        }

        /**
         * Gets an instance of the class (called via reflection).
         *
         * @param config The current Configuration.
         * @param options The pattern options, may be null. If the first element is "short", only the first line of the
         *                throwable will be formatted.
         * @return new instance of class or null
         */
        public static Yellow newInstance(final Configuration config, final String[] options) {
            return newInstance(Yellow.class, NAME, config, options);
        }
    }

    /**
     * Gets an instance of the class (called via reflection).
     *
     * @param config The current Configuration.
     * @param options The pattern options, may be null. If the first element is "short", only the first line of the
     *                throwable will be formatted.
     * @return new instance of class or null
     */
    protected static <T extends AbstractStyleNameConverter> T newInstance(final Class<T> asnConverterClass,
                                                                          final String name, final Configuration config,
                                                                          final String[] options) {
        final List<PatternFormatter> formatters = toPatternFormatterList(config, options);
        if (formatters == null) {
            return null;
        }
        try {
            final Constructor<T> constructor = asnConverterClass.getConstructor(List.class, String.class);
            return constructor.newInstance(formatters, AnsiEscape.createSequence(name));
        } catch (final SecurityException e) {
            LOGGER.error(e.toString(), e);
        } catch (final NoSuchMethodException e) {
            LOGGER.error(e.toString(), e);
        } catch (final IllegalArgumentException e) {
            LOGGER.error(e.toString(), e);
        } catch (final InstantiationException e) {
            LOGGER.error(e.toString(), e);
        } catch (final IllegalAccessException e) {
            LOGGER.error(e.toString(), e);
        } catch (final InvocationTargetException e) {
            LOGGER.error(e.toString(), e);
        }
        return null;
    }

    /**
     * Creates a list of PatternFormatter from the given configuration and options or null if no pattern is supplied.
     *
     * @param config A configuration.
     * @param options pattern options.
     * @return a list of PatternFormatter from the given configuration and options or null if no pattern is supplied.
     */
    private static List<PatternFormatter> toPatternFormatterList(final Configuration config, final String[] options) {
        if (options.length == 0 || options[0] == null) {
            LOGGER.error("No pattern supplied on style for config=" + config);
            return null;
        }
        final PatternParser parser = PatternLayout.createPatternParser(config);
        if (parser == null) {
            LOGGER.error("No PatternParser created for config=" + config + ", options=" + Arrays.toString(options));
            return null;
        }
        return parser.parse(options[0]);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @PerformanceSensitive("allocation")
    public void format(final LogEvent event, final StringBuilder toAppendTo) {
        final int start = toAppendTo.length();
        for (int i = 0; i < formatters.size(); i++) {
            final PatternFormatter formatter = formatters.get(i);
            formatter.format(event, toAppendTo);
        }
        if (toAppendTo.length() > start) {
            toAppendTo.insert(start, style);
            toAppendTo.append(AnsiEscape.getDefaultStyle());
        }
    }
}
