/*
 * 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.sling.commons.osgi;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * This is a helper class to parse manifest header entries.
 */
public class ManifestHeader {

    /**
     * A header can have several entries separated by comma.
     */
    public interface Entry {

        /**
         * @return The value of the entry.
         */
        String getValue();

        /**
         * @return The attributes specified for this entry.
         */
        NameValuePair[] getAttributes();

        /**
         * @return The directives for this entry.
         */
        NameValuePair[] getDirectives();

        String getAttributeValue(String name);

        String getDirectiveValue(String name);
    }

    /** The entries for this header. */
    private Entry[] entries = new Entry[0];

    /**
     * Add new entries from parsing.
     */
    private void add(Entry[] paths) {
        if ( paths != null && paths.length > 0 ) {
            final Entry[] copy = new Entry[this.entries.length + paths.length];
            System.arraycopy(this.entries, 0, copy, 0, this.entries.length);
            System.arraycopy(paths, 0, copy, this.entries.length, paths.length);
            this.entries = copy;
        }
    }

    /**
     * @return Return the entries for this header.
     */
    public Entry[] getEntries() {
        return this.entries;
    }

    /**
     * Directives and attributes are simple name/value pairs.
     */
    public final static class NameValuePair {

        private final String name;
        private final String value;

        public NameValuePair(String name, String value) {
            this.name = name;
            this.value = value;
        }

        public String getName() {
            return name;
        }

        public String getValue() {
            return value;
        }
    }

    private static final String CLASS_PATH_SEPARATOR = ",";
    private static final String PACKAGE_SEPARATOR = ";";
    private static final String DIRECTIVE_SEPARATOR = ":=";
    private static final String ATTRIBUTE_SEPARATOR = "=";

    /**
     * Parse headers
     * Like this: path; path; dir1:=dirval1; dir2:=dirval2; attr1=attrval1; attr2=attrval2,
     *            path; path; dir1:=dirval1; dir2:=dirval2; attr1=attrval1; attr2=attrval2
     * The returned object maintains the order of entries (paths), directives and attributes.
     * @param header Header name
     * @return Parsed header or null if not found
     */
    public static ManifestHeader parse(String header) {
        final ManifestHeader entry = new ManifestHeader();

        if (header != null) {
            if (header.length() == 0) {
                throw new IllegalArgumentException("A header cannot be an empty string.");
            }

            final String[] clauseStrings = parseDelimitedString(header, CLASS_PATH_SEPARATOR);
            if ( clauseStrings != null ) {
                for(final String clause : clauseStrings) {
                    entry.add(parseStandardHeaderClause(clause));
                }
            }
        }

        return (entry.getEntries().length == 0) ? null : entry;
    }

    /**
     * Parse a clause
     * Like this: path; path; dir1:=dirval1; dir2:=dirval2; attr1=attrval1; attr2=attrval2
     */
    private static ManifestHeader.Entry[] parseStandardHeaderClause(String clauseString)
    throws IllegalArgumentException {
        // Break string into semi-colon delimited pieces.
        String[] pieces = parseDelimitedString(clauseString, PACKAGE_SEPARATOR);

        // Count the number of different paths; paths
        // will not have an '=' in their string. This assumes
        // that paths come first, before directives and
        // attributes.
        int pathCount = 0;
        for (int pieceIdx = 0; pieceIdx < pieces.length; pieceIdx++) {
            if (pieces[pieceIdx].indexOf('=') >= 0) {
                break;
            }
            pathCount++;
        }

        // Error if no paths were specified.
        if (pathCount == 0) {
            throw new IllegalArgumentException(
                "No paths specified in header: " + clauseString);
        }

        // Create an array of paths.
        PathImpl[] paths = new PathImpl[pathCount];
        for(int i=0;i<pathCount;i++) {
            paths[i] = new PathImpl(pieces[i]);
        }

        // Parse the directives/attributes
        // and keep the order
        // for simpliefied checking if a directive/attribute is used twice, we keep
        // two collections: one for the values and one for the names
        final List<ManifestHeader.NameValuePair> dirsList = new ArrayList<ManifestHeader.NameValuePair>();
        final Set<String> dirsNames = new HashSet<String>();
        final List<ManifestHeader.NameValuePair> attrsList = new ArrayList<ManifestHeader.NameValuePair>();
        final Set<String> attrsNames = new HashSet<String>();

        int idx = -1;
        String sep = null;
        for (int pieceIdx = pathCount; pieceIdx < pieces.length; pieceIdx++) {

            if ((idx = pieces[pieceIdx].indexOf(DIRECTIVE_SEPARATOR)) >= 0) {
                sep = DIRECTIVE_SEPARATOR;
            } else if ((idx = pieces[pieceIdx].indexOf(ATTRIBUTE_SEPARATOR)) >= 0) {
                sep = ATTRIBUTE_SEPARATOR;
            } else {
                throw new IllegalArgumentException("Not a directive/attribute: " + clauseString);
            }

            final String key = pieces[pieceIdx].substring(0, idx).trim();
            String value = pieces[pieceIdx].substring(idx + sep.length()).trim();

            // Remove quotes, if value is quoted.
            if (value.startsWith("\"") && value.endsWith("\"")) {
                value = value.substring(1, value.length() - 1);
            }

            // Save the directive/attribute in the appropriate array.
            if (sep.equals(DIRECTIVE_SEPARATOR)) {
                // Check for duplicates.
                if (dirsNames.contains(key)) {
                    throw new IllegalArgumentException("Duplicate directive: " + key);
                }
                dirsList.add(new ManifestHeader.NameValuePair(key, value));
                dirsNames.add(key);
            } else {
                // Check for duplicates.
                if (attrsNames.contains(key)) {
                    throw new IllegalArgumentException("Duplicate attribute: " + key);
                }
                attrsList.add(new ManifestHeader.NameValuePair(key, value));
                attrsNames.add(key);
            }
        }
        // Create directive array.
        ManifestHeader.NameValuePair[] dirs =
            dirsList.toArray(new ManifestHeader.NameValuePair[dirsList.size()]);

        // Create attribute array.
        ManifestHeader.NameValuePair[] attrs =
            attrsList.toArray(new ManifestHeader.NameValuePair[attrsList.size()]);

        // now set attributes and directives for each path
        for(int i=0;i<pathCount;i++) {
            paths[i].init(dirs, attrs);
        }

        return paths;
    }

    private static final int CHAR = 1;
    private static final int DELIMITER = 2;
    private static final int STARTQUOTE = 4;
    private static final int ENDQUOTE = 8;

    /**
     * Parses delimited string and returns an array containing the tokens. This
     * parser obeys quotes, so the delimiter character will be ignored if it is
     * inside of a quote. This method assumes that the quote character is not
     * included in the set of delimiter characters.
     * @param value the delimited string to parse.
     * @param delim the characters delimiting the tokens.
     * @return an array of string tokens or null if there were no tokens.
     **/
    private static String[] parseDelimitedString(String value, String delim) {
        if (value == null) {
           value = "";
        }

        final List<String> list = new ArrayList<String>();

        final StringBuilder sb = new StringBuilder();

        int expecting = (CHAR | DELIMITER | STARTQUOTE);

        for (int i = 0; i < value.length(); i++) {
            char c = value.charAt(i);

            boolean isDelimiter = (delim.indexOf(c) >= 0);
            boolean isQuote = (c == '"');

            if (isDelimiter && ((expecting & DELIMITER) > 0)) {
                list.add(sb.toString().trim());
                sb.delete(0, sb.length());
                expecting = (CHAR | DELIMITER | STARTQUOTE);
            } else if (isQuote && ((expecting & STARTQUOTE) > 0)) {
                sb.append(c);
                expecting = CHAR | ENDQUOTE;
            } else if (isQuote && ((expecting & ENDQUOTE) > 0)) {
                sb.append(c);
                expecting = (CHAR | STARTQUOTE | DELIMITER);
            } else if ((expecting & CHAR) > 0) {
                sb.append(c);
            } else {
                throw new IllegalArgumentException("Invalid delimited string: " + value);
            }
        }

        if (sb.length() > 0) {
            list.add(sb.toString().trim());
        }

        if ( list.size() == 0 ) {
            return null;
        }
        return list.toArray(new String[list.size()]);
    }

    protected static final class PathImpl implements ManifestHeader.Entry {

        private final String value;

        private NameValuePair[] attributes;
        private NameValuePair[] directives;

        public PathImpl(final String path) {
            this.value = path;
        }

        public void init(NameValuePair[] dirs, NameValuePair[] attrs) {
            this.directives = dirs;
            this.attributes = attrs;
        }

        /**
         * @see org.apache.sling.commons.osgi.ManifestHeader.Entry#getAttributes()
         */
        public NameValuePair[] getAttributes() {
            return this.attributes;
        }

        /**
         * @see org.apache.sling.commons.osgi.ManifestHeader.Entry#getDirectives()
         */
        public NameValuePair[] getDirectives() {
            return this.directives;
        }

        /**
         * @see org.apache.sling.commons.osgi.ManifestHeader.Entry#getValue()
         */
        public String getValue() {
            return this.value;
        }

        public String getAttributeValue(String name) {
            String v = null;
            int index = 0;
            while ( v == null && index < attributes.length ) {
                if ( attributes[index].getName().equals(name) ) {
                    v = attributes[index].getValue();
                }
                index++;
            }
            return v;
        }

        public String getDirectiveValue(String name) {
            String v = null;
            int index = 0;
            while ( v == null && index < directives.length ) {
                if ( directives[index].getName().equals(name) ) {
                    v = directives[index].getValue();
                }
                index++;
            }
            return v;
        }
    }
}
