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

import java.io.InterruptedIOException;
import java.util.Locale;
import java.util.Properties;

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.status.StatusLogger;
import org.apache.logging.log4j.util.PropertiesUtil;
import org.apache.logging.log4j.util.Strings;

/**
 * A convenience class to convert property values to specific types.
 */
public final class OptionConverter {

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

    private static final String DELIM_START = "${";
    private static final char DELIM_STOP = '}';
    private static final int DELIM_START_LEN = 2;
    private static final int DELIM_STOP_LEN = 1;
    private static final int ONE_K = 1024;

    /**
     * OptionConverter is a static class.
     */
    private OptionConverter() {
    }

    public static String[] concatenateArrays(final String[] l, final String[] r) {
        final int len = l.length + r.length;
        final String[] a = new String[len];

        System.arraycopy(l, 0, a, 0, l.length);
        System.arraycopy(r, 0, a, l.length, r.length);

        return a;
    }

    public static String convertSpecialChars(final String s) {
        char c;
        final int len = s.length();
        final StringBuilder sbuf = new StringBuilder(len);

        int i = 0;
        while (i < len) {
            c = s.charAt(i++);
            if (c == '\\') {
                c = s.charAt(i++);
                switch (c) {
                case 'n':
                    c = '\n';
                    break;
                case 'r':
                    c = '\r';
                    break;
                case 't':
                    c = '\t';
                    break;
                case 'f':
                    c = '\f';
                    break;
                case 'b':
                    c = '\b';
                    break;
                case '"':
                    c = '\"';
                    break;
                case '\'':
                    c = '\'';
                    break;
                case '\\':
                    c = '\\';
                    break;
                default:
                    // there is no default case.
                }
            }
            sbuf.append(c);
        }
        return sbuf.toString();
    }

    public static Object instantiateByKey(final Properties props, final String key, final Class<?> superClass,
                                   final Object defaultValue) {

        // Get the value of the property in string form
        final String className = findAndSubst(key, props);
        if (className == null) {
            LOGGER.error("Could not find value for key {}", key);
            return defaultValue;
        }
        // Trim className to avoid trailing spaces that cause problems.
        return OptionConverter.instantiateByClassName(className.trim(), superClass,
            defaultValue);
    }

    /**
     * If <code>value</code> is "true", then {@code true} is
     * returned. If <code>value</code> is "false", then
     * {@code false} is returned. Otherwise, <code>default</code> is
     * returned.
     *
     * <p>Case of value is unimportant.</p>
     * @param value The value to convert.
     * @param defaultValue The default value.
     * @return true or false, depending on the value and/or default.
     */
    public static boolean toBoolean(final String value, final boolean defaultValue) {
        if (value == null) {
            return defaultValue;
        }
        final String trimmedVal = value.trim();
        if ("true".equalsIgnoreCase(trimmedVal)) {
            return true;
        }
        if ("false".equalsIgnoreCase(trimmedVal)) {
            return false;
        }
        return defaultValue;
    }

    /**
     * Convert the String value to an int.
     * @param value The value as a String.
     * @param defaultValue The default value.
     * @return The value as an int.
     */
    public static int toInt(final String value, final int defaultValue) {
        if (value != null) {
            final String s = value.trim();
            try {
                return Integer.parseInt(s);
            } catch (final NumberFormatException e) {
                LOGGER.error("[{}] is not in proper int form.", s, e);
            }
        }
        return defaultValue;
    }

    public static Level toLevel(String value, Level defaultValue) {
        if(value == null) {
            return defaultValue;
        }

        value = value.trim();

        int hashIndex = value.indexOf('#');
        if (hashIndex == -1) {
            if("NULL".equalsIgnoreCase(value)) {
                return null;
            } else {
                // no class name specified : use standard Level class
                return Level.toLevel(value, defaultValue);
            }
        }

        Level result = defaultValue;

        String clazz = value.substring(hashIndex+1);
        String levelName = value.substring(0, hashIndex);

        // This is degenerate case but you never know.
        if("NULL".equalsIgnoreCase(levelName)) {
            return null;
        }

        LOGGER.debug("toLevel" + ":class=[" + clazz + "]"
                + ":pri=[" + levelName + "]");

        try {
            Class customLevel = Loader.loadClass(clazz);

            // get a ref to the specified class' static method
            // toLevel(String, org.apache.log4j.Level)
            Class[] paramTypes = new Class[] { String.class, Level.class
            };
            java.lang.reflect.Method toLevelMethod =
                    customLevel.getMethod("toLevel", paramTypes);

            // now call the toLevel method, passing level string + default
            Object[] params = new Object[] {levelName, defaultValue};
            Object o = toLevelMethod.invoke(null, params);

            result = (Level) o;
        } catch(ClassNotFoundException e) {
            LOGGER.warn("custom level class [" + clazz + "] not found.");
        } catch(NoSuchMethodException e) {
            LOGGER.warn("custom level class [" + clazz + "]"
                    + " does not have a class function toLevel(String, Level)", e);
        } catch(java.lang.reflect.InvocationTargetException e) {
            if (e.getTargetException() instanceof InterruptedException
                    || e.getTargetException() instanceof InterruptedIOException) {
                Thread.currentThread().interrupt();
            }
            LOGGER.warn("custom level class [" + clazz + "]" + " could not be instantiated", e);
        } catch(ClassCastException e) {
            LOGGER.warn("class [" + clazz + "] is not a subclass of org.apache.log4j.Level", e);
        } catch(IllegalAccessException e) {
            LOGGER.warn("class ["+clazz+ "] cannot be instantiated due to access restrictions", e);
        } catch(RuntimeException e) {
            LOGGER.warn("class ["+clazz+"], level [" + levelName + "] conversion failed.", e);
        }
        return result;
    }

    /**
     *
     * @param value The size of the file as a String.
     * @param defaultValue The default value.
     * @return The size of the file as a long.
     */
    public static long toFileSize(final String value, final long defaultValue) {
        if (value == null) {
            return defaultValue;
        }

        String str = value.trim().toUpperCase(Locale.ENGLISH);
        long multiplier = 1;
        int index;

        if ((index = str.indexOf("KB")) != -1) {
            multiplier = ONE_K;
            str = str.substring(0, index);
        } else if ((index = str.indexOf("MB")) != -1) {
            multiplier = ONE_K * ONE_K;
            str = str.substring(0, index);
        } else if ((index = str.indexOf("GB")) != -1) {
            multiplier = ONE_K * ONE_K * ONE_K;
            str = str.substring(0, index);
        }
        try {
            return Long.parseLong(str) * multiplier;
        } catch (final NumberFormatException e) {
            LOGGER.error("[{}] is not in proper int form.", str);
            LOGGER.error("[{}] not in expected format.", value, e);
        }
        return defaultValue;
    }

    /**
     * Find the value corresponding to <code>key</code> in
     * <code>props</code>. Then perform variable substitution on the
     * found value.
     * @param key The key to locate.
     * @param props The properties.
     * @return The String after substitution.
     */
    public static String findAndSubst(final String key, final Properties props) {
        final String value = props.getProperty(key);
        if (value == null) {
            return null;
        }

        try {
            return substVars(value, props);
        } catch (final IllegalArgumentException e) {
            LOGGER.error("Bad option value [{}].", value, e);
            return value;
        }
    }

    /**
     * Instantiate an object given a class name. Check that the
     * <code>className</code> is a subclass of
     * <code>superClass</code>. If that test fails or the object could
     * not be instantiated, then <code>defaultValue</code> is returned.
     *
     * @param className    The fully qualified class name of the object to instantiate.
     * @param superClass   The class to which the new object should belong.
     * @param defaultValue The object to return in case of non-fulfillment
     * @return The created object.
     */
    public static Object instantiateByClassName(final String className, final Class<?> superClass,
                                         final Object defaultValue) {
        if (className != null) {
            try {
                final Class<?> classObj = Loader.loadClass(className);
                if (!superClass.isAssignableFrom(classObj)) {
                    LOGGER.error("A \"{}\" object is not assignable to a \"{}\" variable.", className,
                        superClass.getName());
                    LOGGER.error("The class \"{}\" was loaded by [{}] whereas object of type [{}] was loaded by [{}].",
                        superClass.getName(), superClass.getClassLoader(), classObj.getName());
                    return defaultValue;
                }
                return classObj.newInstance();
            } catch (final Exception e) {
                LOGGER.error("Could not instantiate class [{}].", className, e);
            }
        }
        return defaultValue;
    }


    /**
     * Perform variable substitution in string <code>val</code> from the
     * values of keys found in the system propeties.
     *
     * <p>The variable substitution delimiters are <b>${</b> and <b>}</b>.</p>
     *
     * <p>For example, if the System properties contains "key=value", then
     * the call</p>
     * <pre>
     * String s = OptionConverter.substituteVars("Value of key is ${key}.");
     * </pre>
     * <p>
     * will set the variable <code>s</code> to "Value of key is value.".
     * </p>
     * <p>If no value could be found for the specified key, then the
     * <code>props</code> parameter is searched, if the value could not
     * be found there, then substitution defaults to the empty string.</p>
     *
     * <p>For example, if system properties contains no value for the key
     * "inexistentKey", then the call
     * </p>
     * <pre>
     * String s = OptionConverter.subsVars("Value of inexistentKey is [${inexistentKey}]");
     * </pre>
     * <p>
     * will set <code>s</code> to "Value of inexistentKey is []"
     * </p>
     * <p>An {@link java.lang.IllegalArgumentException} is thrown if
     * <code>val</code> contains a start delimeter "${" which is not
     * balanced by a stop delimeter "}". </p>
     *
     * @param val The string on which variable substitution is performed.
     * @param props The properties to use for substitution.
     * @return The String after substitution.
     * @throws IllegalArgumentException if <code>val</code> is malformed.
     */
    public static String substVars(final String val, final Properties props) throws
        IllegalArgumentException {

        final StringBuilder sbuf = new StringBuilder();

        int i = 0;
        int j;
        int k;

        while (true) {
            j = val.indexOf(DELIM_START, i);
            if (j == -1) {
                // no more variables
                if (i == 0) { // this is a simple string
                    return val;
                }
                // add the tail string which contails no variables and return the result.
                sbuf.append(val.substring(i, val.length()));
                return sbuf.toString();
            }
            sbuf.append(val.substring(i, j));
            k = val.indexOf(DELIM_STOP, j);
            if (k == -1) {
                throw new IllegalArgumentException(Strings.dquote(val)
                    + " has no closing brace. Opening brace at position " + j
                    + '.');
            }
            j += DELIM_START_LEN;
            final String key = val.substring(j, k);
            // first try in System properties
            String replacement = PropertiesUtil.getProperties().getStringProperty(key, null);
            // then try props parameter
            if (replacement == null && props != null) {
                replacement = props.getProperty(key);
            }

            if (replacement != null) {
                // Do variable substitution on the replacement string
                // such that we can solve "Hello ${x2}" as "Hello p1"
                // the where the properties are
                // x1=p1
                // x2=${x1}
                final String recursiveReplacement = substVars(replacement, props);
                sbuf.append(recursiveReplacement);
            }
            i = k + DELIM_STOP_LEN;
        }
    }
}
