package org.apache.commons.jcs3.utils.config;

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

import java.util.Properties;

import org.apache.commons.jcs3.log.Log;
import org.apache.commons.jcs3.log.LogManager;

/**
 * This class is based on the log4j class org.apache.log4j.helpers.OptionConverter that was made by
 * Ceki G&uuml;lc&uuml; Simon Kitching; Avy Sharell (sharell@online.fr) Anders Kristensen Matthieu
 * Verbert (mve@zurich.ibm.com) A convenience class to convert property values to specific types.
 */
public class OptionConverter
{
    /** The logger */
    private static final Log log = LogManager.getLog( OptionConverter.class );

    /** System property delimter */
    private static final String DELIM_START = "${";

    /** System property delimter */
    private static final char DELIM_STOP = '}';

    /** System property delimter start length */
    private static final int DELIM_START_LEN = 2;

    /** System property delimter end length */
    private static final int DELIM_STOP_LEN = 1;

    /** No instances please. */
    private OptionConverter()
    {
    }

    /**
     * Combines two arrays.
     * @param l
     * @param r
     * @return String[]
     */
    public static String[] concatanateArrays( 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;
    }

    /**
     * Escapes special characters.
     *
     * @param s
     * @return String
     */
    public static String convertSpecialChars( final String s )
    {
        char c;
        final int len = s.length();
        final StringBuilder sb = new StringBuilder( len );

        int i = 0;
        while ( i < len )
        {
            c = s.charAt( i++ );
            if ( c == '\\' )
            {
                c = s.charAt( i++ );
                if ( c == 'n' )
                {
                    c = '\n';
                }
                else if ( c == 'r' )
                {
                    c = '\r';
                }
                else if ( c == 't' )
                {
                    c = '\t';
                }
                else if ( c == 'f' )
                {
                    c = '\f';
                }
                else if ( c == '\b' )
                {
                    c = '\b';
                }
                else if ( c == '\"' )
                {
                    c = '\"';
                }
                else if ( c == '\'' )
                {
                    c = '\'';
                }
                else if ( c == '\\' )
                {
                    c = '\\';
                }
            }
            sb.append( c );
        }
        return sb.toString();
    }

    /**
     * Very similar to <code>System.getProperty</code> except that the {@link SecurityException} is
     * hidden.
     * @param key The key to search for.
     * @param def The default value to return.
     * @return the string value of the system property, or the default value if there is no property
     *         with that key.
     * @since 1.1
     */

    public static String getSystemProperty( final String key, final String def )
    {
        try
        {
            return System.getProperty( key, def );
        }
        catch ( final Throwable e )
        {
            // MS-Java throws com.ms.security.SecurityExceptionEx
            log.debug( "Was not allowed to read system property \"{0}\".", key );
            return def;
        }
    }

    /**
     * Creates an object for the className value of the key.
     *
     * @param props
     * @param key
     * @param defaultValue
     * @return Object that was created
     */
    public static <T> T instantiateByKey( final Properties props, final String key, final T defaultValue )
    {

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

    /**
     * If <code>value</code> is "true", then <code>true</code> is returned. If <code>value</code> is
     * "false", then <code>true</code> is returned. Otherwise, <code>default</code> is returned.
     *
     * Case of value is unimportant.
     * @param value
     * @param defaultValue
     * @return Object
     */
    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;
    }

    /**
     * Converts to int.
     *
     * @param value
     * @param defaultValue
     * @return 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 )
            {
                log.error( "[{0}] is not in proper int form.", s, e );
            }
        }
        return defaultValue;
    }

    /**
     * @param value
     * @param defaultValue
     * @return long
     */
    public static long toFileSize( final String value, final long defaultValue )
    {
        if ( value == null )
        {
            return defaultValue;
        }

        String s = value.trim().toUpperCase();
        long multiplier = 1;
        int index;

        if ( ( index = s.indexOf( "KB" ) ) != -1 )
        {
            multiplier = 1024;
            s = s.substring( 0, index );
        }
        else if ( ( index = s.indexOf( "MB" ) ) != -1 )
        {
            multiplier = 1024 * 1024;
            s = s.substring( 0, index );
        }
        else if ( ( index = s.indexOf( "GB" ) ) != -1 )
        {
            multiplier = 1024 * 1024 * 1024;
            s = s.substring( 0, index );
        }
        if ( s != null )
        {
            try
            {
                return Long.parseLong(s) * multiplier;
            }
            catch ( final NumberFormatException e )
            {
                log.error( "[{0}] is not in proper int form.", s);
                log.error( "[{0}] 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
     * @param props
     * @return substituted string
     */

    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 )
        {
            log.error( "Bad option value [{0}]", 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 defaultValue The object to return in case of non-fulfillment
     * @return instantiated object
     */

    public static <T> T instantiateByClassName( final String className, final T defaultValue )
    {
        if ( className != null )
        {
            try
            {
                final Class<?> classObj = Class.forName( className );
                final Object o = classObj.newInstance();

                try
                {
                    @SuppressWarnings("unchecked") // CCE catched
                    final
                    T t = (T) o;
                    return t;
                }
                catch (final ClassCastException e)
                {
                    log.error( "A \"{0}\" object is not assignable to the "
                            + "generic variable.", className );
                    return defaultValue;
                }
            }
            catch ( final ClassNotFoundException | InstantiationException | IllegalAccessException e )
            {
                log.error( "Could not instantiate class [{0}]", className, e );
            }
        }
        return defaultValue;
    }

    /**
     * Perform variable substitution in string <code>val</code> from the values of keys found in the
     * system properties.
     *
     * The variable substitution delimiters are <b>${ </b> and <b>} </b>.
     *
     * For example, if the System properties contains "key=value", then the call
     *
     * <pre>
     * String s = OptionConverter.substituteVars( &quot;Value of key is ${key}.&quot; );
     * </pre>
     *
     * will set the variable <code>s</code> to "Value of key is value.".
     *
     * 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.
     *
     * For example, if system properties contains no value for the key "inexistentKey", then the call
     *
     * <pre>
     * String s = OptionConverter.subsVars( &quot;Value of inexistentKey is [${inexistentKey}]&quot; );
     * </pre>
     *
     * will set <code>s</code> to "Value of inexistentKey is []"
     * <p>
     * An {@link java.lang.IllegalArgumentException}is thrown if <code>val</code> contains a start
     * delimiter "${" which is not balanced by a stop delimiter "}".
     * </p>
     * <p>
     * <b>Author </b> Avy Sharell
     * </p>
     * @param val The string on which variable substitution is performed.
     * @param props
     * @return String
     * @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 )
            {
                if ( i == 0 )
                {
                    return val;
                }
                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( '"' + 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 = getSystemProperty( key, null );
            // then try props parameter
            if ( replacement == null && props != null )
            {
                replacement = props.getProperty( key );
            }

            if ( replacement != null )
            {
                sbuf.append( replacement );
            }
            i = k + DELIM_STOP_LEN;
        }
    }
}
