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

import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Random;
import java.util.Set;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Strings
 *
 */

public final class Strings
{
    private static final String NUMBERS = "0123456789";
    private static final String LETTERS = "abcdefghijklmnopqrstuvwxwy";
    private static final String OTHERS = "_-";
    private static final char[] CHARACTERS = (NUMBERS + LETTERS + LETTERS.toUpperCase() + OTHERS).toCharArray();
    private static final Random RANDOM = new Random();

    private Strings()
    {
    }

    public static String randomAlphaNumericString(int maxLength)
    {
        char[] result = new char[maxLength];
        for (int i = 0; i < maxLength; i++)
        {
            result[i] = CHARACTERS[RANDOM.nextInt(CHARACTERS.length)];
        }
        return new String(result);
    }

    private static final byte[] EMPTY = new byte[0];

    private static final ThreadLocal<char[]> charbuf = new ThreadLocal<char[]>()
    {
        public char[] initialValue()
        {
            return new char[4096];
        }
    };

    public static final byte[] toUTF8(String str)
    {
        if (str == null)
        {
            return EMPTY;
        }
        else
        {
            final int size = str.length();
            char[] chars = charbuf.get();
            if (size > chars.length)
            {
                chars = new char[Math.max(size, 2*chars.length)];
                charbuf.set(chars);
            }

            str.getChars(0, size, chars, 0);
            final byte[] bytes = new byte[size];
            for (int i = 0; i < size; i++)
            {
                if (chars[i] > 127)
                {
                    try
                    {
                        return str.getBytes("UTF-8");
                    }
                    catch (UnsupportedEncodingException e)
                    {
                        throw new RuntimeException(e);
                    }
                }

                bytes[i] = (byte) chars[i];
            }
            return bytes;
        }
    }

    public static final String fromUTF8(byte[] bytes)
    {
        try
        {
            return new String(bytes, "UTF-8");
        }
        catch (UnsupportedEncodingException e)
        {
            throw new RuntimeException(e);
        }
    }

    private static final Pattern VAR = Pattern.compile("(?:\\$\\{([^\\}]*)\\})|(?:\\$(\\$))");

    public static Resolver chain(Resolver... resolvers)
    {
        Resolver resolver;
        if(resolvers.length == 0)
        {
            resolver =  NULL_RESOLVER;
        }
        else
        {
            resolver = resolvers[resolvers.length - 1];
            for (int i = resolvers.length - 2; i >= 0; i--)
            {
                resolver = new ChainedResolver(resolvers[i], resolver);
            }
        }
        return resolver;
    }

    public static byte[] decodeBase64(String base64String)
    {
        base64String = base64String.replaceAll("\\s","");
        if(!base64String.matches("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"))
        {
            throw new IllegalArgumentException("Cannot convert string '"+ base64String+ "'to a byte[] - it does not appear to be base64 data");
        }

        return Base64.getDecoder().decode(base64String);
    }

    public static interface Resolver
    {
        String resolve(String variable, final Resolver resolver);
    }

    private static final Resolver NULL_RESOLVER =
            new Resolver()
            {
                @Override
                public String resolve(final String variable, final Resolver resolver)
                {
                    return null;
                }
            };

    public static class MapResolver implements Resolver
    {

        private final Map<String,String> map;

        public MapResolver(Map<String,String> map)
        {
            this.map = map;
        }

        public String resolve(String variable, final Resolver resolver)
        {
            return map.get(variable);
        }
    }

    public static class PropertiesResolver implements Resolver
    {

        private final Properties properties;

        public PropertiesResolver(Properties properties)
        {
            this.properties = properties;
        }

        public String resolve(String variable, final Resolver resolver)
        {
            return properties.getProperty(variable);
        }
    }

    public static class ChainedResolver implements Resolver
    {
        private final Resolver primary;
        private final Resolver secondary;

        public ChainedResolver(Resolver primary, Resolver secondary)
        {
            this.primary = primary;
            this.secondary = secondary;
        }

        public String resolve(String variable, final Resolver resolver)
        {
            String result = primary.resolve(variable, resolver);
            if (result == null)
            {
                result = secondary.resolve(variable, resolver);
            }
            return result;
        }
    }

    public static final Resolver ENV_VARS_RESOLVER = new Resolver()
        {
            @Override
            public String resolve(final String variable, final Resolver resolver)
            {
                return System.getenv(variable);
            }
        };


    public static final Resolver JAVA_SYS_PROPS_RESOLVER = new Resolver()
    {
        @Override
        public String resolve(final String variable, final Resolver resolver)
        {
            return System.getProperty(variable);
        }
    };


    public static final Resolver SYSTEM_RESOLVER = chain(JAVA_SYS_PROPS_RESOLVER, ENV_VARS_RESOLVER);

    public static final String expand(String input)
    {
        return expand(input, SYSTEM_RESOLVER);
    }

    public static final String expand(String input, Resolver resolver)
    {
        return expand(input, resolver, new Stack<String>(),true);
    }
    public static final String expand(String input, boolean failOnUnresolved, Resolver... resolvers)
    {
        return expand(input, chain(resolvers), new Stack<String>(), failOnUnresolved);
    }

    private static final String expand(String input, Resolver resolver, Stack<String> stack, boolean failOnUnresolved)
    {
        if (input == null)
        {
            return null;
        }
        Matcher m = VAR.matcher(input);
        StringBuffer result = new StringBuffer();
        while (m.find())
        {
            String var = m.group(1);
            if (var == null)
            {
                String esc = m.group(2);
                if ("$".equals(esc))
                {
                    m.appendReplacement(result, Matcher.quoteReplacement("$"));
                }
                else
                {
                    throw new IllegalArgumentException(esc);
                }
            }
            else
            {
                m.appendReplacement(result, Matcher.quoteReplacement(resolve(var, resolver, stack, failOnUnresolved)));
            }
        }
        m.appendTail(result);
        return result.toString();
    }

    private static final String resolve(String var,
                                        Resolver resolver,
                                        Stack<String> stack,
                                        final boolean failOnUnresolved)
    {
        if (stack.contains(var))
        {
            throw new IllegalArgumentException
                (String.format("recursively defined variable: %s stack=%s", var,
                               stack));
        }

        String result = resolver.resolve(var, resolver);
        if (result == null)
        {
            if(failOnUnresolved)
            {
                throw new IllegalArgumentException("no such variable: " + var);
            }
            else
            {
                return "${"+var+"}";
            }
        }

        stack.push(var);
        try
        {
            return expand(result, resolver, stack, failOnUnresolved);
        }
        finally
        {
            stack.pop();
        }
    }

    public static final String join(String sep, Iterable items)
    {
        StringBuilder result = new StringBuilder();

        for (Object o : items)
        {
            if (result.length() > 0)
            {
                result.append(sep);
            }
            result.append(o.toString());
        }

        return result.toString();
    }

    public static final String join(String sep, Object[] items)
    {
        return join(sep, Arrays.asList(items));
    }

    public static final List<String> split(String listAsString)
    {
        if(listAsString != null && !"".equals(listAsString))
        {
            return Arrays.asList(listAsString.split("\\s*,\\s*"));
        }
        return Collections.emptyList();
    }

    public static String printMap(Map<String,Object> map)
    {
        StringBuilder sb = new StringBuilder();
        sb.append("<");
        if (map != null)
        {
            for(Map.Entry<String,Object> entry : map.entrySet())
            {
                sb.append(entry.getKey()).append(" = ").append(entry.getValue()).append(" ");
            }
        }
        sb.append(">");
        return sb.toString();
    }


    public static Resolver createSubstitutionResolver(String prefix, LinkedHashMap<String,String> substitutions)
    {
        return new StringSubstitutionResolver(prefix, substitutions);
    }

    private static class StringSubstitutionResolver implements Resolver
    {

        private final ThreadLocal<Set<String>> _stack = new ThreadLocal<>();

        private final LinkedHashMap<String, String> _substitutions;
        private final String _prefix;

        private StringSubstitutionResolver(String prefix, LinkedHashMap<String, String> substitutions)
        {
            _prefix = prefix;
            _substitutions = substitutions;
        }

        @Override
        public String resolve(final String variable, final Resolver resolver)
        {
            boolean clearStack = false;
            Set<String> currentStack = _stack.get();
            if(currentStack == null)
            {
                currentStack = new HashSet<>();
                _stack.set(currentStack);
                clearStack = true;
            }

            try
            {
                if(currentStack.contains(variable))
                {
                    throw new IllegalArgumentException("The value of attribute " + variable + " is defined recursively");

                }


                if (variable.startsWith(_prefix))
                {
                    currentStack.add(variable);
                    String expanded = resolver.resolve(variable.substring(_prefix.length()), resolver);
                    currentStack.remove(variable);
                    if(expanded != null)
                    {
                        for(Map.Entry<String,String> entry : _substitutions.entrySet())
                        {
                            expanded = expanded.replace(entry.getKey(), entry.getValue());
                        }
                    }
                    return expanded;
                }
                else
                {
                    return null;
                }

            }
            finally
            {

                if(clearStack)
                {
                    _stack.remove();
                }
            }
        }
    }
}
