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

#ifndef _DECAF_UTIL_PROPERTIES_H_
#define _DECAF_UTIL_PROPERTIES_H_

#include <vector>
#include <string>
#include <decaf/util/Config.h>
#include <decaf/util/StlMap.h>
#include <decaf/io/InputStream.h>
#include <decaf/io/OutputStream.h>
#include <decaf/lang/Pointer.h>
#include <decaf/lang/exceptions/IllegalArgumentException.h>
#include <decaf/lang/exceptions/NullPointerException.h>
#include <decaf/io/IOException.h>

namespace decaf{
namespace io{
    class Reader;
    class Writer;
}
namespace util{

    class PropertiesInternal;

    /**
     * Java-like properties class for mapping string names to string values.
     * <p>
     * The Properties list contains a key value pair of properties that can be loaded and
     * stored to a stream.  Each Properties instance can contain an internal Properties list
     * that contains default values for keys not found in the Properties List.
     * <p>
     * The Properties list if a Thread Safe class, it can be shared amongst objects in
     * multiple threads without the need for additional synchronization.
     *
     * @since 1.0
     */
    class DECAF_API Properties {
    private:

        PropertiesInternal* internal;

    protected:

        /**
         * Default list used to answer for any keys not found in the properties list, can
         * be filled in by another implementation of this class.
         */
        decaf::lang::Pointer<Properties> defaults;

    public:

        Properties();

        Properties(const Properties& src);

        virtual ~Properties();

        /**
         * Assignment Operator
         *
         * @param src
         *      The Properties list to copy to this List.
         *
         * @return a reference to this List for use in chaining.
         */
        Properties& operator=(const Properties& src);

        /**
         * Returns true if the properties object is empty.
         *
         * @return true if empty
         */
        bool isEmpty() const;

        /**
         * @return The number of Properties in this Properties Object.
         */
        int size() const;

        /**
         * Looks up the value for the given property.
         *
         * @param name
         *      The name of the property to be looked up.
         *
         * @return the value of the property with the given name, if it
         *         exists.  If it does not exist, returns NULL.
         */
        const char* getProperty(const std::string& name) const;

        /**
         * Looks up the value for the given property.
         *
         * @param name
         *      The name of the property to be looked up.
         * @param defaultValue
         *      The value to be returned if the given property does not exist.
         *
         * @return The value of the property specified by <code>name</code>, if it
         *         exists, otherwise the <code>defaultValue</code>.
         */
        std::string getProperty(const std::string& name, const std::string& defaultValue) const;

        /**
         * Sets the value for a given property.  If the property already
         * exists, overwrites the value.
         *
         * @param name
         *      The name of the value to be written.
         * @param value
         *      The value to be written.
         *
         * @return the old value of the property or empty string if not set.
         */
        std::string setProperty(const std::string& name, const std::string& value);

        /**
         * Check to see if the Property exists in the set.
         *
         * @param name
         *      The property name to check for in this properties set.
         *
         * @return true if property exists, false otherwise.
         */
        bool hasProperty(const std::string& name) const;

        /**
         * Removes the property with the given name.
         *
         * @param name
         *      The name of the property to remove.
         *
         * @return the previous value of the property if set, or empty string.
         */
        std::string remove(const std::string& name);

        /**
         * Returns an enumeration of all the keys in this property list, including distinct keys
         * in the default property list if a key of the same name has not already been found from
         * the main properties list.
         *
         * @return a set of keys in this property list where the key and its corresponding value are
         *          strings, including the keys in the default property list.
         */
        std::vector<std::string> propertyNames() const;

        /**
         * Method that serializes the contents of the property map to an array.
         *
         * @return list of pairs where the first is the name and the second
         *         is the value.
         */
        std::vector<std::pair<std::string, std::string> > toArray() const;

        /**
         * Copies the contents of the given properties object to this one, if the
         * given Properties instance in empty then this List is not modified.
         *
         * @param source
         *      The source properties object.
         */
        void copy(const Properties& source);

        /**
         * Clones this object.
         *
         * @return a replica of this object.
         */
        Properties* clone() const;

        /**
         * Clears all properties from the map.
         */
        void clear();

        /**
         * Test whether two Properties objects are equivalent.  Two Properties
         * Objects are considered equivalent when they each contain the same number
         * of elements and each key / value pair contained within the two are equal.
         *
         * This comparison does not check the contents of the Defaults instance.
         *
         * @param source
         *      The Properties object to compare this instance to.
         *
         * @return true if the contents of the two Properties objects are the same.
         */
        bool equals(const Properties& source) const;

        /**
         * Formats the contents of the Properties Object into a string that can be logged, etc.
         *
         * @return string value of this object.
         */
        std::string toString() const;

        /**
         * Reads a property list (key and element pairs) from the input byte stream. The
         * input stream is in a simple line-oriented format as specified in load(Reader) and
         * is assumed to use the ISO 8859-1 character encoding.
         *
         * This method does not close the stream upon its return.
         *
         * @param stream
         *      The stream to read the properties data from.
         *
         * @throw IOException if there is an error while reading from the stream.
         * @throw IllegalArgumentException if malformed data is found while reading the properties.
         * @throw NullPointerException if the passed stream is Null.
         */
        void load(decaf::io::InputStream* stream);

        /**
         * Reads a property list (key and element pairs) from the input character stream in a
         * simple line-oriented format.
         * <p>
         * Properties are processed in terms of lines. There are two kinds of line, natural lines
         * and logical lines. A natural line is defined as a line of characters that is terminated
         * either by a set of line terminator characters (\n or \r or \r\n) or by the end of the
         * stream. A natural line may be either a blank line, a comment line, or hold all or some
         * of a key-element pair. A logical line holds all the data of a key-element pair, which
         * may be spread out across several adjacent natural lines by escaping the line terminator
         * sequence with a backslash character \. Note that a comment line cannot be extended in
         * this manner; every natural line that is a comment must have its own comment indicator,
         * as described below. Lines are read from input until the end of the stream is reached.
         * <p>
         * A natural line that contains only white space characters is considered blank and is
         * ignored. A comment line has an ASCII '#' or '!' as its first non-white space character;
         * comment lines are also ignored and do not encode key-element information. In addition
         * to line terminators, this format considers the characters space (' '), tab ('\t'),
         * and form feed ('\f') to be white space.
         * <p>
         * If a logical line is spread across several natural lines, the backslash escaping the
         * line terminator sequence, the line terminator sequence, and any white space at the
         * start of the following line have no affect on the key or element values. The remainder
         * of the discussion of key and element parsing (when loading) will assume all the
         * characters constituting the key and element appear on a single natural line after line
         * continuation characters have been removed. Note that it is not sufficient to only
         * examine the character preceding a line terminator sequence to decide if the line
         * terminator is escaped; there must be an odd number of contiguous backslashes for the
         * line terminator to be escaped. Since the input is processed from left to right, a
         * non-zero even number of 2n contiguous backslashes before a line terminator (or
         * elsewhere) encodes n backslashes after escape processing.
         * <p>
         * The key contains all of the characters in the line starting with the first non-white
         * space character and up to, but not including, the first unescaped '=', ':', or white
         * space character other than a line terminator. All of these key termination characters
         * may be included in the key by escaping them with a preceding backslash character; for
         * example,
         *
         *    \:\=
         *
         * would be the two-character key ":=". Line terminator characters can be included using
         * \r and \n escape sequences. Any white space after the key is skipped; if the first
         * non-white space character after the key is '=' or ':', then it is ignored and any white
         * space characters after it are also skipped. All remaining characters on the line become
         * part of the associated element string; if there are no remaining characters, the element
         * is the empty string "". Once the raw character sequences constituting the key and
         * element are identified, escape processing is performed as described above.
         * <p>
         * As an example, each of the following three lines specifies the key "Truth" and the
         * associated element value "Beauty":
         * <p>
         *     Truth = Beauty
         *             Truth:Beauty
         *         Truth                  :Beauty
         * <p>
         * As another example, the following three lines specify a single property:
         * <p>
         * fruits                           apple, banana, pear, \
         *                                  cantaloupe, watermelon, \
         *                                  kiwi, mango
         * <p>
         * The key is "fruits" and the associated element is:
         *     "apple, banana, pear, cantaloupe, watermelon, kiwi, mango"
         * <p>
         * Note that a space appears before each \ so that a space will appear after each comma
         * in the final result; the \, line terminator, and leading white space on the continuation
         * line are merely discarded and are not replaced by one or more other characters.
         * <p>
         * As a third example, the line:
         *
         *   cheeses
         *
         * specifies that the key is "cheeses" and the associated element is the empty string "".
         * <p>
         * Characters in keys and elements can be represented in escape sequences similar to those
         * used for character and string literals (see §3.3 and §3.10.6 of the Java Language
         * Specification). The differences from the character escape sequences and Unicode escapes
         * used for characters and strings are:
         *
         *   - Octal escapes are not recognized.
         *   - The character sequence \b does not represent a backspace character.
         *   - The method does not treat a backslash character, \, before a non-valid escape
         *     character as an error; the backslash is silently dropped. For example, in a C++
         *     string the sequence "\z" would cause a compile time error. In contrast, this
         *     method silently drops the backslash. Therefore, this method treats the two
         *     character sequence "\b" as equivalent to the single character 'b'.
         *   - Escapes are not necessary for single and double quotes; however, by the rule above,
         *     single and double quote characters preceded by a backslash still yield single and
         *     double quote characters, respectively.
         *
         * This method does not close the Reader upon its return.
         *
         * @param reader
         *      The Reader that provides an character stream as input.
         *
         * @throw IOException if there is an error while reading from the stream.
         * @throw IllegalArgumentException if malformed data is found while reading the properties.
         * @throw NullPointerException if the passed stream is Null.
         */
        void load(decaf::io::Reader* reader);

        /**
         * Writes this property list (key and element pairs) in this Properties table to the
         * output stream in a format suitable for loading into a Properties table using the
         * load(InputStream) method.
         * <p>
         * Properties from the defaults table of this Properties table (if any) are not
         * written out by this method.
         * <p>
         * This method outputs the comments, properties keys and values in the same format
         * as specified in store(Writer), with the following differences:
         *
         *   - The stream is written using the ISO 8859-1 character encoding.
         *   - Characters not in Latin-1 in the comments are written as \uxxxx for their
         *     appropriate unicode hexadecimal value xxxx.
         *   - Characters less than \u0020 and characters greater than \u007E in property keys
         *     or values are written as \uxxxx for the appropriate hexadecimal value xxxx.
         *
         * After the entries have been written, the output stream is flushed. The output stream
         * remains open after this method returns.
         *
         * @param out
         *      The OutputStream instance to write the properties to.
         * @param comment
         *      A description of these properties that is written to the output stream.
         *
         * @throw IOException if there is an error while writing from the stream.
         * @throw NullPointerException if the passed stream is Null.
         */
        void store(decaf::io::OutputStream* out, const std::string& comment);

        /**
         * Writes this property list (key and element pairs) in this Properties table to the output
         * character stream in a format that can be read by the load(Reader) method.
         * <p>
         * Properties from the defaults table of this Properties table (if any) are not written
         * out by this method.
         * <p>
         * If the comments argument is not empty, then an ASCII # character, the comments string,
         * and a line separator are first written to the output stream. Thus, the comments can
         * serve as an identifying comment. Any one of a line feed ('\n'), a carriage return ('\r'),
         * or a carriage return followed immediately by a line feed in comments is replaced by a
         * line separator generated by the Writer and if the next character in comments is not
         * character # or character ! then an ASCII # is written out after that line separator.
         * <p>
         * Next, a comment line is always written, consisting of an ASCII # character, the current
         * date and time (as if produced by the toString method of Date for the current time), and
         * a line separator as generated by the Writer.
         * <p>
         * Then every entry in this Properties table is written out, one per line. For each entry
         * the key string is written, then an ASCII =, then the associated element string. For the
         * key, all space characters are written with a preceding \ character. For the element,
         * leading space characters, but not embedded or trailing space characters, are written
         * with a preceding \ character. The key and element characters #, !, =, and : are written
         * with a preceding backslash to ensure that they are properly loaded.
         * <p>
         * After the entries have been written, the output stream is flushed. The output stream
         * remains open after this method returns.
         *
         * @param writer
         *      The Writer instance to use to output the properties.
         * @param comments
         *      A description of these properties that is written before writing the properties.
         *
         * @throw IOException if there is an error while writing from the stream.
         * @throw NullPointerException if the passed stream is Null.
         */
        void store(decaf::io::Writer* writer, const std::string& comments);

    private:

        void selectProperties(decaf::util::StlMap<std::string, std::string>& selectProperties) const;

    };

}}

#endif /*_DECAF_UTIL_PROPERTIES_H_*/
