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

import java.io.BufferedReader;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

/*
 * ### things to add: - should probably be a SourceTracker
 * - if an entry is removed, should there be an option to remove comments
 * just before the entry(a la javadoc)?
 * - should we have an option to clean up whitespace?
 * - potentially would be interesting to add comments about each
 * property that OpenJPA adds to this object. We'd want to make the
 * automatic comment-removing code work first, though, so that if
 * someone then removed the property, the comments would go away.
 * - would be neat if DuplicateKeyException could report line numbers of
 * offending entries.
 * - putAll() with another FormatPreservingProperties should be smarter
 */

/**
 * A specialization of {@link Properties} that stores its contents
 * in the same order and with the same formatting as was used to read
 * the contents from an input stream. This is useful because it means
 * that a properties file loaded via this object and then written
 * back out later on will only be different where changes or
 * additions were made.
 * By default, the {@link #store} method in this class does not
 * behave the same as {@link Properties#store}. You can cause an
 * instance to approximate the behavior of {@link Properties#store}
 * by invoking {@link #setDefaultEntryDelimiter} with <code>=</code>,
 * {@link #setAddWhitespaceAfterDelimiter} with <code>false</code>, and
 * {@link #setAllowDuplicates} with <code>true</code>. However, this
 * will only influence how the instance will write new values, not how
 * it will write existing key-value pairs that are modified.
 * In conjunction with a conservative output writer, it is
 * possible to only write to disk changes / additions.
 * This implementation does not permit escaped ' ', '=', ':'
 * characters in key names.
 *
 * @since 0.3.3
 */
public class FormatPreservingProperties extends Properties {

    
    private static final long serialVersionUID = 1L;

    private static Localizer _loc = Localizer.forPackage
        (FormatPreservingProperties.class);

    private char defaultEntryDelimiter = ':';
    private boolean addWhitespaceAfterDelimiter = true;
    private boolean allowDuplicates = false;
    private boolean insertTimestamp = false;

    private PropertySource source;
    private LinkedHashSet newKeys = new LinkedHashSet();
    private HashSet modifiedKeys = new HashSet();

    // marker that indicates that we're not deserializing
    private transient boolean isNotDeserializing = true;
    private transient boolean isLoading = false;

    public FormatPreservingProperties() {
        this(null);
    }

    public FormatPreservingProperties(Properties defaults) {
        super(defaults);
    }

    /**
     * The character to use as a delimiter between property keys and values.
     *
     * @param defaultEntryDelimiter either ':' or '='
     */
    public void setDefaultEntryDelimiter(char defaultEntryDelimiter) {
        this.defaultEntryDelimiter = defaultEntryDelimiter;
    }

    /**
     * See {@link #setDefaultEntryDelimiter}
     */
    public char getDefaultEntryDelimiter() {
        return this.defaultEntryDelimiter;
    }

    /**
     * If set to <code>true</code>, this properties object will add a
     * space after the delimiter character(if the delimiter is not
     * the space character). Else, this will not add a space.
     * Default value: <code>true</code>. Note that {@link
     * Properties#store} never writes whitespace.
     */
    public void setAddWhitespaceAfterDelimiter(boolean add) {
        this.addWhitespaceAfterDelimiter = add;
    }

    /**
     * If set to <code>true</code>, this properties object will add a
     * space after the delimiter character(if the delimiter is not
     * the space character). Else, this will not add a space.
     * Default value: <code>true</code>. Note that {@link
     * Properties#store} never writes whitespace.
     */
    public boolean getAddWhitespaceAfterDelimiter() {
        return this.addWhitespaceAfterDelimiter;
    }

    /**
     * If set to <code>true</code>, this properties object will add a
     * timestamp to the beginning of the file, just after the header
     * (if any) is printed. Else, this will not add a timestamp.
     * Default value: <code>false</code>. Note that {@link
     * Properties#store} always writes a timestamp.
     */
    public void setInsertTimestamp(boolean insertTimestamp) {
        this.insertTimestamp = insertTimestamp;
    }

    /**
     * If set to <code>true</code>, this properties object will add a
     * timestamp to the beginning of the file, just after the header
     * (if any) is printed. Else, this will not add a timestamp.
     * Default value: <code>false</code>. Note that {@link
     * Properties#store} always writes a timestamp.
     */
    public boolean getInsertTimestamp() {
        return this.insertTimestamp;
    }

    /**
     * If set to <code>true</code>, duplicate properties are allowed, and
     * the last property setting in the input will overwrite any previous
     * settings. If set to <code>false</code>, duplicate property definitions
     * in the input will cause an exception to be thrown during {@link #load}.
     * Default value: <code>false</code>. Note that {@link
     * Properties#store} always allows duplicates.
     */
    public void setAllowDuplicates(boolean allowDuplicates) {
        this.allowDuplicates = allowDuplicates;
    }

    /**
     * If set to <code>true</code>, duplicate properties are allowed, and
     * the last property setting in the input will overwrite any previous
     * settings. If set to <code>false</code>, duplicate property definitions
     * in the input will cause an exception to be thrown during {@link #load}.
     * Default value: <code>false</code>. Note that {@link
     * Properties#store} always allows duplicates.
     */
    public boolean getAllowDuplicates() {
        return this.allowDuplicates;
    }

    @Override
    public String getProperty(String key) {
        return super.getProperty(key);
    }

    @Override
    public String getProperty(String key, String defaultValue) {
        return super.getProperty(key, defaultValue);
    }

    @Override
    public Object setProperty(String key, String value) {
        return put(key, value);
    }

    /**
     * Circumvents the superclass {@link #putAll} implementation,
     * putting all the key-value pairs via {@link #put}.
     */
    @Override
    public synchronized void putAll(Map m) {
        Map.Entry e;
        for (Iterator iter = m.entrySet().iterator(); iter.hasNext();) {
            e = (Map.Entry) iter.next();
            put(e.getKey(), e.getValue());
        }
    }

    /**
     * Removes the key from the bookkeeping collectiotns as well.
     */
    @Override
    public synchronized Object remove(Object key) {
        newKeys.remove(key);
        return super.remove(key);
    }

    @Override
    public synchronized void clear() {
        super.clear();

        if (source != null)
            source.clear();

        newKeys.clear();
        modifiedKeys.clear();
    }

    @Override
    public synchronized Object clone() {
        FormatPreservingProperties c = (FormatPreservingProperties)
            super.clone();

        if (source != null)
            c.source = (PropertySource) source.clone();

        if (modifiedKeys != null)
            c.modifiedKeys = (HashSet) modifiedKeys.clone();

        if (newKeys != null) {
            c.newKeys = new LinkedHashSet();
            c.newKeys.addAll(newKeys);
        }

        return c;
    }

    private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();
    }

    private void readObject(ObjectInputStream in)
        throws IOException, ClassNotFoundException {
        in.defaultReadObject();

        isNotDeserializing = true;
    }

    @Override
    public synchronized Object put(Object key, Object val) {
        Object o = super.put(key, val);

        // if we're no longer loading from properties and this put
        // represents an actual change in value, mark the modification
        // or addition in the bookkeeping collections.
        if (!isLoading && isNotDeserializing && !val.equals(o)) {
            if (o != null)
                modifiedKeys.add(key);
            else if (!newKeys.contains(key))
                newKeys.add(key);
        }
        return o;
    }

    /**
     * Loads the properties in <code>in</code>, according to the rules
     * described in {@link Properties#load}. If {@link #getAllowDuplicates}
     * returns <code>true</code>, this will throw a {@link
     * DuplicateKeyException} if duplicate property declarations are
     * encountered.
     *
     * @see Properties#load
     */
    @Override
    public synchronized void load(InputStream in) throws IOException {
        isLoading = true;
        try {
            loadProperties(in);
        } finally {
            isLoading = false;
        }
    }

    private void loadProperties(InputStream in) throws IOException {
        source = new PropertySource();

        PropertyLineReader reader = new PropertyLineReader(in, source);

        Set loadedKeys = new HashSet();

        for (PropertyLine l;
            (l = reader.readPropertyLine()) != null && source.add(l);) {
            String line = l.line.toString();

            char c = 0;
            int pos = 0;

            while (pos < line.length() && isSpace(c = line.charAt(pos)))
                pos++;

            if ((line.length() - pos) == 0
                || line.charAt(pos) == '#' || line.charAt(pos) == '!')
                continue;

            StringBuilder key = new StringBuilder();
            while (pos < line.length() && !isSpace(c = line.charAt(pos++))
                && c != '=' && c != ':') {
                if (c == '\\') {
                    if (pos == line.length()) {
                        l.append(line = reader.readLine());
                        pos = 0;
                        while (pos < line.length()
                            && isSpace(c = line.charAt(pos)))
                            pos++;
                    } else {
                        pos = readEscape(line, pos, key);
                    }
                } else {
                    key.append(c);
                }
            }

            boolean isDelim = (c == ':' || c == '=');

            for (; pos < line.length()
                && isSpace(c = line.charAt(pos)); pos++)
                ;

            if (!isDelim && (c == ':' || c == '=')) {
                pos++;
                while (pos < line.length() && isSpace(c = line.charAt(pos)))
                    pos++;
            }

            StringBuilder element = new StringBuilder(line.length() - pos);

            while (pos < line.length()) {
                c = line.charAt(pos++);
                if (c == '\\') {
                    if (pos == line.length()) {
                        l.append(line = reader.readLine());

                        if (line == null)
                            break;

                        pos = 0;
                        while (pos < line.length()
                            && isSpace(c = line.charAt(pos)))
                            pos++;
                        element.ensureCapacity(line.length() - pos +
                            element.length());
                    } else {
                        pos = readEscape(line, pos, element);
                    }
                } else
                    element.append(c);
            }

            if (!loadedKeys.add(key.toString()) && !allowDuplicates)
                throw new DuplicateKeyException(key.toString(),
                    getProperty(key.toString()), element.toString());

            l.setPropertyKey(key.toString());
            l.setPropertyValue(element.toString());
            put(key.toString(), element.toString());
        }
    }

    /**
     * Read the next escaped character: handle newlines, tabs, returns, and
     * form feeds with the appropriate escaped character, then try to
     * decode unicode characters. Finally, just add the character explicitly.
     *
     * @param source the source of the characters
     * @param pos the position at which to start reading
     * @param value the value we are appending to
     * @return the position after the reading is done
     */
    private static int readEscape(String source, int pos, StringBuilder value) {
        char c = source.charAt(pos++);
        switch (c) {
            case 'n':
                value.append('\n');
                break;
            case 't':
                value.append('\t');
                break;
            case 'f':
                value.append('\f');
                break;
            case 'r':
                value.append('\r');
                break;
            case 'u':
                if (pos + 4 <= source.length()) {
                    char uni = (char) Integer.parseInt
                        (source.substring(pos, pos + 4), 16);
                    value.append(uni);
                    pos += 4;
                }
                break;
            default:
                value.append(c);
                break;
        }

        return pos;
    }

    private static boolean isSpace(char ch) {
        return Character.isWhitespace(ch);
    }

    @Override
    public void save(OutputStream out, String header) {
        try {
            store(out, header);
        } catch (IOException ex) {
        }
    }

    @Override
    public void store(OutputStream out, String header) throws IOException {
        boolean endWithNewline = source != null && source.endsInNewline;

        // Must be ISO-8859-1 ecoding according to Properties.load javadoc
        PrintWriter writer = new PrintWriter
            (new OutputStreamWriter(out, "ISO-8859-1"), false);

        if (header != null)
            writer.println("#" + header);

        if (insertTimestamp)
            writer.println("#" + Calendar.getInstance().getTime());

        List lines = new LinkedList();
        // first write all the existing props as they were initially read
        if (source != null)
            lines.addAll(source);

        // next write out new keys, then the rest of the keys
        LinkedHashSet keys = new LinkedHashSet();
        keys.addAll(newKeys);
        keys.addAll(keySet());

        lines.addAll(keys);

        keys.remove(null);

        boolean needsNewline = false;

        for (Iterator i = lines.iterator(); i.hasNext();) {
            Object next = i.next();

            if (next instanceof PropertyLine) {
                if (((PropertyLine) next).write(writer, keys, needsNewline))
                    needsNewline = i.hasNext();
            } else if (next instanceof String) {
                String key = (String) next;
                if (keys.remove(key)) {
                    if (writeProperty(key, writer, needsNewline)) {
                        needsNewline = i.hasNext() && keys.size() > 0;

                        // any new or modified properties will cause
                        // the file to end with a newline
                        endWithNewline = true;
                    }
                }
            }
        }

        // make sure we end in a newline if the source ended in it
        if (endWithNewline)
            writer.println();

        writer.flush();
    }

    private boolean writeProperty(String key, PrintWriter writer,
        boolean needsNewline) {
        StringBuilder s = new StringBuilder();

        if (key == null)
            return false;

        String val = getProperty(key);
        if (val == null)
            return false;

        formatValue(key, s, true);
        s.append(defaultEntryDelimiter);
        if (addWhitespaceAfterDelimiter)
            s.append(' ');
        formatValue(val, s, false);

        if (needsNewline)
            writer.println();

        writer.print(s);

        return true;
    }

    /**
     * Format the given string as an encoded value for storage. This will
     * perform any necessary escaping of special characters.
     *
     * @param str the value to encode
     * @param buf the buffer to which to append the encoded value
     * @param isKey if true, then the string is a Property key, otherwise
     * it is a value
     */
    private static void formatValue(String str, StringBuilder buf,
        boolean isKey) {
        if (isKey) {
            buf.setLength(0);
            buf.ensureCapacity(str.length());
        } else {
            buf.ensureCapacity(buf.length() + str.length());
        }

        boolean escapeSpace = true;
        int size = str.length();

        for (int i = 0; i < size; i++) {
            char c = str.charAt(i);

            if (c == '\n')
                buf.append("\\n");
            else if (c == '\r')
                buf.append("\\r");
            else if (c == '\t')
                buf.append("\\t");
            else if (c == '\f')
                buf.append("\\f");
            else if (c == ' ')
                buf.append(escapeSpace ? "\\ " : " ");
            else if (c == '\\' || c == '!' || c == '#' || c == '=' || c == ':')
                buf.append('\\').append(c);
            else if (c < ' ' || c > '~')
                buf.append("\\u0000".substring(0, 6 - Integer.toHexString(c).
                    length())).append(Integer.toHexString(c));
            else
                buf.append(c);

            if (c != ' ')
                escapeSpace = isKey;
        }
    }

    public static class DuplicateKeyException extends RuntimeException {

        
        private static final long serialVersionUID = 1L;

        public DuplicateKeyException(String key, Object firstVal,
            String secondVal) {
            super(_loc.get("dup-key", key, firstVal, secondVal).getMessage());
        }
    }

    /**
     * Contains the original line of the properties file: can be a
     * proper key/value pair, or a comment, or just whitespace.
     */
    private class PropertyLine implements Serializable {

        
        private static final long serialVersionUID = 1L;
        private final StringBuilder line = new StringBuilder();
        private String propertyKey;
        private String propertyValue;

        public PropertyLine(String line) {
            this.line.append(line);
        }

        public void append(String newline) {
            line.append(J2DoPrivHelper.getLineSeparator());
            line.append(newline);
        }

        public void setPropertyKey(String propertyKey) {
            this.propertyKey = propertyKey;
        }

        public String getPropertyKey() {
            return this.propertyKey;
        }

        public void setPropertyValue(String propertyValue) {
            this.propertyValue = propertyValue;
        }

        public String getPropertyValue() {
            return this.propertyValue;
        }

        /**
         * Write the given line. It will only be written if the line is a
         * comment, or if it is a property and its value is unchanged
         * from the original.
         *
         * @param pw the PrintWriter to which the write
         * @return whether or not this was a known key
         */
        public boolean write(PrintWriter pw, Collection keys,
            boolean needsNewline) {
            // no property? It may be a comment or just whitespace
            if (propertyKey == null) {
                if (needsNewline)
                    pw.println();
                pw.print(line.toString());
                return true;
            }

            // check to see if we are the same value we initially read:
            // if so, then just write it back exactly as it was read
            if (propertyValue != null && containsKey(propertyKey) &&
                (propertyValue.equals(getProperty(propertyKey)) ||
                    (!newKeys.contains(propertyKey) &&
                        !modifiedKeys.contains(propertyKey)))) {
                if (needsNewline)
                    pw.println();
                pw.print(line.toString());

                keys.remove(propertyKey);

                return true;
            }

            // if we have modified or added the specified key, then write
            // it back to the same location in the file from which it
            // was originally read, so that it will be in the proximity
            // to the comment
            if (containsKey(propertyKey) &&
                (modifiedKeys.contains(propertyKey) ||
                    newKeys.contains(propertyKey))) {
                while (keys.remove(propertyKey)) ;
                return writeProperty(propertyKey, pw, needsNewline);
            }

            // this is a new or changed property: don't do anything
            return false;
        }
    }

    private class PropertyLineReader extends BufferedReader {

        public PropertyLineReader(InputStream in, PropertySource source)
            throws IOException {
            // Must be ISO-8859-1 ecoding according to Properties.load javadoc
            super(new InputStreamReader(new LineEndingStream(in, source),
                "ISO-8859-1"));
        }

        public PropertyLine readPropertyLine() throws IOException {
            String l = readLine();
            if (l == null)
                return null;

            PropertyLine pl = new PropertyLine(l);
            return pl;
        }
    }

    /**
     * Simple FilterInputStream that merely remembers if the last
     * character that it read was a newline or not.
     */
    private static class LineEndingStream extends FilterInputStream {

        private final PropertySource source;

        LineEndingStream(InputStream in, PropertySource source) {
            super(in);

            this.source = source;
        }

        @Override
        public int read() throws IOException {
            int c = super.read();
            source.endsInNewline = (c == '\n' || c == '\r');
            return c;
        }

        @Override
        public int read(byte[] b, int off, int len) throws IOException {
            int n = super.read(b, off, len);
            if (n > 0)
                source.endsInNewline =
                    (b[n + off - 1] == '\n' || b[n + off - 1] == '\r');
            return n;
        }
    }

    static class PropertySource extends LinkedList
        implements Cloneable, Serializable {

        
        private static final long serialVersionUID = 1L;
        private boolean endsInNewline = false;
    }
}
