/*
 * 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.commons.vfs2.provider;

import org.apache.commons.vfs2.FileName;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileType;
import org.apache.commons.vfs2.VFS;
import org.apache.commons.vfs2.util.Os;

/**
 * Utilities for dealing with URIs. See RFC 2396 for details.
 */
public final class UriParser {

    /**
     * The set of valid separators. These are all converted to the normalized one. Does <i>not</i> contain the
     * normalized separator
     */
    // public static final char[] separators = {'\\'};
    public static final char TRANS_SEPARATOR = '\\';

    /**
     * The normalised separator to use.
     */
    private static final char SEPARATOR_CHAR = FileName.SEPARATOR_CHAR;

    private static final int HEX_BASE = 16;

    private static final int BITS_IN_HALF_BYTE = 4;

    private static final char LOW_MASK = 0x0F;

    /**
     * Encodes and appends a string to a StringBuilder.
     *
     * @param buffer The StringBuilder to append to.
     * @param unencodedValue The String to encode and append.
     * @param reserved characters to encode.
     */
    public static void appendEncoded(final StringBuilder buffer, final String unencodedValue, final char[] reserved) {
        final int offset = buffer.length();
        buffer.append(unencodedValue);
        encode(buffer, offset, unencodedValue.length(), reserved);
    }

    public static void canonicalizePath(final StringBuilder buffer, final int offset, final int length,
            final FileNameParser fileNameParser) throws FileSystemException {
        int index = offset;
        int count = length;
        for (; count > 0; count--, index++) {
            final char ch = buffer.charAt(index);
            if (ch == '%') {
                if (count < 3) {
                    throw new FileSystemException("vfs.provider/invalid-escape-sequence.error",
                            buffer.substring(index, index + count));
                }

                // Decode
                final int dig1 = Character.digit(buffer.charAt(index + 1), HEX_BASE);
                final int dig2 = Character.digit(buffer.charAt(index + 2), HEX_BASE);
                if (dig1 == -1 || dig2 == -1) {
                    throw new FileSystemException("vfs.provider/invalid-escape-sequence.error",
                            buffer.substring(index, index + 3));
                }
                final char value = (char) (dig1 << BITS_IN_HALF_BYTE | dig2);

                final boolean match = value == '%' || fileNameParser.encodeCharacter(value);

                if (match) {
                    // this is a reserved character, not allowed to decode
                    index += 2;
                    count -= 2;
                    continue;
                }

                // Replace
                buffer.setCharAt(index, value);
                buffer.delete(index + 1, index + 3);
                count -= 2;
            } else if (fileNameParser.encodeCharacter(ch)) {
                // Encode
                final char[] digits = { Character.forDigit((ch >> BITS_IN_HALF_BYTE) & LOW_MASK, HEX_BASE),
                        Character.forDigit(ch & LOW_MASK, HEX_BASE) };
                buffer.setCharAt(index, '%');
                buffer.insert(index + 1, digits);
                index += 2;
            }
        }
    }

    /**
     * Decodes the String.
     *
     * @param uri The String to decode.
     * @throws FileSystemException if an error occurs.
     */
    public static void checkUriEncoding(final String uri) throws FileSystemException {
        decode(uri);
    }

    /**
     * Removes %nn encodings from a string.
     *
     * @param encodedStr The encoded String.
     * @return The decoded String.
     * @throws FileSystemException if an error occurs.
     */
    public static String decode(final String encodedStr) throws FileSystemException {
        if (encodedStr == null) {
            return null;
        }
        if (encodedStr.indexOf('%') < 0) {
            return encodedStr;
        }
        final StringBuilder buffer = new StringBuilder(encodedStr);
        decode(buffer, 0, buffer.length());
        return buffer.toString();
    }

    /**
     * Removes %nn encodings from a string.
     *
     * @param buffer StringBuilder containing the string to decode.
     * @param offset The position in the string to start decoding.
     * @param length The number of characters to decode.
     * @throws FileSystemException if an error occurs.
     */
    public static void decode(final StringBuilder buffer, final int offset, final int length)
            throws FileSystemException {
        int index = offset;
        int count = length;
        for (; count > 0; count--, index++) {
            final char ch = buffer.charAt(index);
            if (ch != '%') {
                continue;
            }
            if (count < 3) {
                throw new FileSystemException("vfs.provider/invalid-escape-sequence.error",
                        buffer.substring(index, index + count));
            }

            // Decode
            final int dig1 = Character.digit(buffer.charAt(index + 1), HEX_BASE);
            final int dig2 = Character.digit(buffer.charAt(index + 2), HEX_BASE);
            if (dig1 == -1 || dig2 == -1) {
                throw new FileSystemException("vfs.provider/invalid-escape-sequence.error",
                        buffer.substring(index, index + 3));
            }
            final char value = (char) (dig1 << BITS_IN_HALF_BYTE | dig2);

            // Replace
            buffer.setCharAt(index, value);
            buffer.delete(index + 1, index + 3);
            count -= 2;
        }
    }

    /**
     * Converts "special" characters to their %nn value.
     *
     * @param decodedStr The decoded String.
     * @return The encoded String.
     */
    public static String encode(final String decodedStr) {
        return encode(decodedStr, null);
    }

    /**
     * Converts "special" characters to their %nn value.
     *
     * @param decodedStr The decoded String.
     * @param reserved Characters to encode.
     * @return The encoded String
     */
    public static String encode(final String decodedStr, final char[] reserved) {
        if (decodedStr == null) {
            return null;
        }
        final StringBuilder buffer = new StringBuilder(decodedStr);
        encode(buffer, 0, buffer.length(), reserved);
        return buffer.toString();
    }

    /**
     * Encode an array of Strings.
     *
     * @param strings The array of Strings to encode.
     * @return An array of encoded Strings.
     */
    public static String[] encode(final String[] strings) {
        if (strings == null) {
            return null;
        }
        for (int i = 0; i < strings.length; i++) {
            strings[i] = encode(strings[i]);
        }
        return strings;
    }

    /**
     * Encodes a set of reserved characters in a StringBuilder, using the URI %nn encoding. Always encodes % characters.
     *
     * @param buffer The StringBuilder to append to.
     * @param offset The position in the buffer to start encoding at.
     * @param length The number of characters to encode.
     * @param reserved characters to encode.
     */
    public static void encode(final StringBuilder buffer, final int offset, final int length, final char[] reserved) {
        int index = offset;
        int count = length;
        for (; count > 0; index++, count--) {
            final char ch = buffer.charAt(index);
            boolean match = ch == '%';
            if (reserved != null) {
                for (int i = 0; !match && i < reserved.length; i++) {
                    if (ch == reserved[i]) {
                        match = true;
                        break;
                    }
                }
            }
            if (match) {
                // Encode
                final char[] digits = { Character.forDigit((ch >> BITS_IN_HALF_BYTE) & LOW_MASK, HEX_BASE),
                        Character.forDigit(ch & LOW_MASK, HEX_BASE) };
                buffer.setCharAt(index, '%');
                buffer.insert(index + 1, digits);
                index += 2;
            }
        }
    }

    /**
     * Extracts the first element of a path.
     *
     * @param name StringBuilder containing the path.
     * @return The first element of the path.
     */
    public static String extractFirstElement(final StringBuilder name) {
        final int len = name.length();
        if (len < 1) {
            return null;
        }
        int startPos = 0;
        if (name.charAt(0) == SEPARATOR_CHAR) {
            startPos = 1;
        }
        for (int pos = startPos; pos < len; pos++) {
            if (name.charAt(pos) == SEPARATOR_CHAR) {
                // Found a separator
                final String elem = name.substring(startPos, pos);
                name.delete(startPos, pos + 1);
                return elem;
            }
        }

        // No separator
        final String elem = name.substring(startPos);
        name.setLength(0);
        return elem;
    }

    /**
     * Extract the query String from the URI.
     *
     * @param name StringBuilder containing the URI.
     * @return The query string, if any. null otherwise.
     */
    public static String extractQueryString(final StringBuilder name) {
        for (int pos = 0; pos < name.length(); pos++) {
            if (name.charAt(pos) == '?') {
                final String queryString = name.substring(pos + 1);
                name.delete(pos, name.length());
                return queryString;
            }
        }

        return null;
    }

    /**
     * Extracts the scheme from a URI. Removes the scheme and ':' delimiter from the front of the URI.
     * <p>
     * The scheme is extracted based on the currently supported schemes in the system.  That is to say the schemes
     * supported by the registered providers.
     * </p>
     * <p>
     * This allows us to handle varying scheme's without making assumptions based on the ':' character.  Specifically
     * handle scheme extraction calls for URI parameters that are not actually uri's, but may be names with ':' in them.
     * </p>
     * @param schemes The schemes to check.
     * @param uri The potential URI. May also be a name.
     * @return The scheme name. Returns null if there is no scheme.
     * @since 2.3
     */
    public static String extractScheme(final String[] schemes, final String uri) {
        return extractScheme(schemes, uri, null);
    }

    /**
     * Extracts the scheme from a URI. Removes the scheme and ':' delimiter from the front of the URI.
     * <p>
     * The scheme is extracted based on the given set of schemes. Normally, that is to say the schemes
     * supported by the registered providers.
     * </p>
     * <p>
     * This allows us to handle varying scheme's without making assumptions based on the ':' character. Specifically
     * handle scheme extraction calls for URI parameters that are not actually URI's, but may be names with ':' in them.
     * </p>
     * @param schemes The schemes to check.
     * @param uri The potential URI. May also just be a name.
     * @param buffer Returns the remainder of the URI.
     * @return The scheme name. Returns null if there is no scheme.
     * @since 2.3
     */
    public static String extractScheme(final String[] schemes, final String uri, final StringBuilder buffer) {
        if (buffer != null) {
            buffer.setLength(0);
            buffer.append(uri);
        }
        for(final String scheme : schemes) {
            if(uri.startsWith(scheme + ":")) {
                if (buffer != null) {
                    buffer.delete(0, uri.indexOf(':') + 1);
                }
                return scheme;
            }
        }
        return null;
    }

    /**
     * Extracts the scheme from a URI.
     *
     * @param uri The URI.
     * @return The scheme name. Returns null if there is no scheme.
     * @deprecated Use instead {@link #extractScheme}.  Will be removed in 3.0.
     */
    @Deprecated
    public static String extractScheme(final String uri) {
        return extractScheme(uri, null);
    }

    /**
     * Extracts the scheme from a URI. Removes the scheme and ':' delimiter from the front of the URI.
     *
     * @param uri The URI.
     * @param buffer Returns the remainder of the URI.
     * @return The scheme name. Returns null if there is no scheme.
     * @deprecated Use instead {@link #extractScheme}.  Will be removed in 3.0.
     */
    @Deprecated
    public static String extractScheme(final String uri, final StringBuilder buffer) {
        if (buffer != null) {
            buffer.setLength(0);
            buffer.append(uri);
        }

        final int maxPos = uri.length();
        for (int pos = 0; pos < maxPos; pos++) {
            final char ch = uri.charAt(pos);

            if (ch == ':') {
                // Found the end of the scheme
                final String scheme = uri.substring(0, pos);
                if (scheme.length() <= 1 && Os.isFamily(Os.OS_FAMILY_WINDOWS)) {
                    // This is not a scheme, but a Windows drive letter
                    return null;
                }
                if (buffer != null) {
                    buffer.delete(0, pos + 1);
                }
                return scheme.intern();
            }

            if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
                // A scheme character
                continue;
            }
            if (pos > 0 && ((ch >= '0' && ch <= '9') || ch == '+' || ch == '-' || ch == '.')) {
                // A scheme character (these are not allowed as the first
                // character of the scheme, but can be used as subsequent
                // characters.
                continue;
            }

            // Not a scheme character
            break;
        }

        // No scheme in URI
        return null;
    }

    /**
     * Normalises the separators in a name.
     *
     * @param name The StringBuilder containing the name
     * @return true if the StringBuilder was modified.
     */
    public static boolean fixSeparators(final StringBuilder name) {
        boolean changed = false;
        final int maxlen = name.length();
        for (int i = 0; i < maxlen; i++) {
            final char ch = name.charAt(i);
            if (ch == TRANS_SEPARATOR) {
                name.setCharAt(i, SEPARATOR_CHAR);
                changed = true;
            }
        }
        return changed;
    }

    /**
     * Normalises a path. Does the following:
     * <ul>
     * <li>Removes empty path elements.
     * <li>Handles '.' and '..' elements.
     * <li>Removes trailing separator.
     * </ul>
     *
     * Its assumed that the separators are already fixed.
     *
     * @param path The path to normalize.
     * @return The FileType.
     * @throws FileSystemException if an error occurs.
     *
     * @see #fixSeparators
     */
    public static FileType normalisePath(final StringBuilder path) throws FileSystemException {
        FileType fileType = FileType.FOLDER;
        if (path.length() == 0) {
            return fileType;
        }

        if (path.charAt(path.length() - 1) != '/') {
            fileType = FileType.FILE;
        }

        // Adjust separators
        // fixSeparators(path);

        // Determine the start of the first element
        int startFirstElem = 0;
        if (path.charAt(0) == SEPARATOR_CHAR) {
            if (path.length() == 1) {
                return fileType;
            }
            startFirstElem = 1;
        }

        // Iterate over each element
        int startElem = startFirstElem;
        int maxlen = path.length();
        while (startElem < maxlen) {
            // Find the end of the element
            int endElem = startElem;
            for (; endElem < maxlen && path.charAt(endElem) != SEPARATOR_CHAR; endElem++) {
            }

            final int elemLen = endElem - startElem;
            if (elemLen == 0) {
                // An empty element - axe it
                path.delete(endElem, endElem + 1);
                maxlen = path.length();
                continue;
            }
            if (elemLen == 1 && path.charAt(startElem) == '.') {
                // A '.' element - axe it
                path.delete(startElem, endElem + 1);
                maxlen = path.length();
                continue;
            }
            if (elemLen == 2 && path.charAt(startElem) == '.' && path.charAt(startElem + 1) == '.') {
                // A '..' element - remove the previous element
                if (startElem == startFirstElem) {
                    // Previous element is missing
                    throw new FileSystemException("vfs.provider/invalid-relative-path.error");
                }

                // Find start of previous element
                int pos = startElem - 2;
                for (; pos >= 0 && path.charAt(pos) != SEPARATOR_CHAR; pos--) {
                }
                startElem = pos + 1;

                path.delete(startElem, endElem + 1);
                maxlen = path.length();
                continue;
            }

            // A regular element
            startElem = endElem + 1;
        }

        // Remove trailing separator
        if (!VFS.isUriStyle() && maxlen > 1 && path.charAt(maxlen - 1) == SEPARATOR_CHAR) {
            path.delete(maxlen - 1, maxlen);
        }

        return fileType;
    }

    private UriParser() {
    }
}
