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

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.PushbackReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Properties;

/**
 * <p>A Properties collection which preserves comments and whitespace
 * present in the input stream from which it was loaded.</p>
 * <p>The class defers the usual work of the <a href="http://java.sun.com/j2se/1.3/docs/api/java/util/Properties.html">java.util.Properties</a>
 * class to there, but it also keeps track of the contents of the
 * input stream from which it was loaded (if applicable), so that it can
 * write out the properties in as close a form as possible to the input.</p>
 * <p>If no changes occur to property values, the output should be the same
 * as the input, except for the leading date stamp, as normal for a
 * properties file. Properties added are appended to the file. Properties
 * whose values are changed are changed in place. Properties that are
 * removed are excised. If the <code>removeComments</code> flag is set,
 * then the comments immediately preceding the property are also removed.</p>
 * <p>If a second set of properties is loaded into an existing set, the
 * lines of the second set are added to the end. Note however, that if a
 * property already stored is present in a stream subsequently loaded, then
 * that property is removed before the new value is set. For example,
 * consider the file</p>
 * <pre> # the first line
 * alpha=one
 *
 * # the second line
 * beta=two</pre>
 * <p>This file is loaded, and then the following is also loaded into the
 * same <code>LayoutPreservingProperties</code> object</p>
 * <pre> # association
 * beta=band
 *
 * # and finally
 * gamma=rays</pre>
 * <p>The resulting collection sequence of logical lines depends on whether
 * or not <code>removeComments</code> was set at the time the second stream
 * is loaded. If it is set, then the resulting list of lines is</p>
 * <pre> # the first line
 * alpha=one
 *
 * # association
 * beta=band
 *
 * # and finally
 * gamma=rays</pre>
 * <p>If the flag is not set, then the comment "the second line" is retained,
 * although the key-value pair <code>beta=two</code> is removed.</p>
 */
public class LayoutPreservingProperties extends Properties {
    private String LS = StringUtils.LINE_SEP;

    /**
     * Logical lines have escaping and line continuation taken care
     * of. Comments and blank lines are logical lines; they are not
     * removed.
     */
    private ArrayList logicalLines = new ArrayList();

    /**
     * Position in the <code>logicalLines</code> list, keyed by property name.
     */
    private HashMap keyedPairLines = new HashMap();

    /**
     * Flag to indicate that, when we remove a property from the file, we
     * also want to remove the comments that precede it.
     */
    private boolean removeComments;

    /**
     * Create a new, empty, Properties collection, with no defaults.
     */
    public LayoutPreservingProperties() {
        super();
    }

    /**
     * Create a new, empty, Properties collection, with the specified defaults.
     * @param defaults the default property values
     */
    public LayoutPreservingProperties(final Properties defaults) {
        super(defaults);
    }

    /**
     * Returns <code>true</code> if comments are removed along with
     * properties, or <code>false</code> otherwise. If
     * <code>true</code>, then when a property is removed, the comment
     * preceding it in the original file is removed also.
     * @return <code>true</code> if leading comments are removed when
     * a property is removed; <code>false</code> otherwise
     */
    public boolean isRemoveComments() {
        return removeComments;
    }

    /**
     * Sets the behaviour for comments accompanying properties that
     * are being removed. If <code>true</code>, then when a property
     * is removed, the comment preceding it in the original file is
     * removed also.
     * @param val <code>true</code> if leading comments are to be
     * removed when a property is removed; <code>false</code>
     * otherwise
     */
    public void setRemoveComments(final boolean val) {
        removeComments = val;
    }

    @Override
    public void load(final InputStream inStream) throws IOException {
        final String s = readLines(inStream);
        final byte[] ba = s.getBytes(ResourceUtils.ISO_8859_1);
        final ByteArrayInputStream bais = new ByteArrayInputStream(ba);
        super.load(bais);
    }

    @Override
    public Object put(final Object key, final Object value) throws NullPointerException {
        final Object obj = super.put(key, value);
        // the above call will have failed if key or value are null
        innerSetProperty(key.toString(), value.toString());
        return obj;
    }

    @Override
    public Object setProperty(final String key, final String value)
        throws NullPointerException {
        final Object obj = super.setProperty(key, value);
        // the above call will have failed if key or value are null
        innerSetProperty(key, value);
        return obj;
    }

    /**
     * Store a new key-value pair, or add a new one. The normal
     * functionality is taken care of by the superclass in the call to
     * {@link #setProperty}; this method takes care of this classes
     * extensions.
     * @param key the key of the property to be stored
     * @param value the value to be stored
     */
    private void innerSetProperty(String key, String value) {
        value = escapeValue(value);

        if (keyedPairLines.containsKey(key)) {
            final Integer i = (Integer) keyedPairLines.get(key);
            final Pair p = (Pair) logicalLines.get(i.intValue());
            p.setValue(value);
        } else {
            key = escapeName(key);
            final Pair p = new Pair(key, value);
            p.setNew(true);
            keyedPairLines.put(key, new Integer(logicalLines.size()));
            logicalLines.add(p);
        }
    }

    @Override
    public void clear() {
        super.clear();
        keyedPairLines.clear();
        logicalLines.clear();
    }

    @Override
    public Object remove(final Object key) {
        final Object obj = super.remove(key);
        final Integer i = (Integer) keyedPairLines.remove(key);
        if (null != i) {
            if (removeComments) {
                removeCommentsEndingAt(i.intValue());
            }
            logicalLines.set(i.intValue(), null);
        }
        return obj;
    }

    @Override
    public Object clone() {
        final LayoutPreservingProperties dolly =
            (LayoutPreservingProperties) super.clone();
        dolly.keyedPairLines = (HashMap) this.keyedPairLines.clone();
        dolly.logicalLines = (ArrayList) this.logicalLines.clone();
        final int size = dolly.logicalLines.size();
        for (int j = 0; j < size; j++) {
            final LogicalLine line = (LogicalLine) dolly.logicalLines.get(j);
            if (line instanceof Pair) {
                final Pair p = (Pair) line;
                dolly.logicalLines.set(j, p.clone());
            }
            // no reason to clone other lines are they are immutable
        }
        return dolly;
    }

    /**
     * Echo the lines of the properties (including blanks and comments) to the
     * stream.
     * @param out the stream to write to
     */
    public void listLines(final PrintStream out) {
        out.println("-- logical lines --");
        final Iterator i = logicalLines.iterator();
        while (i.hasNext()) {
            final LogicalLine line = (LogicalLine) i.next();
            if (line instanceof Blank) {
                out.println("blank:   \"" + line + "\"");
            } else if (line instanceof Comment) {
                out.println("comment: \"" + line + "\"");
            } else if (line instanceof Pair) {
                out.println("pair:    \"" + line + "\"");
            }
        }
    }

    /**
     * Save the properties to a file.
     * @param dest the file to write to
     * @throws IOException if save fails
     */
    public void saveAs(final File dest) throws IOException {
        final FileOutputStream fos = new FileOutputStream(dest);
        store(fos, null);
        fos.close();
    }

    @Override
    public void store(final OutputStream out, final String header) throws IOException {
        final OutputStreamWriter osw = new OutputStreamWriter(out, ResourceUtils.ISO_8859_1);

        int skipLines = 0;
        final int totalLines = logicalLines.size();

        if (header != null) {
            osw.write("#" + header + LS);
            if (totalLines > 0
                && logicalLines.get(0) instanceof Comment
                && header.equals(logicalLines.get(0).toString().substring(1))) {
                skipLines = 1;
            }
        }

        // we may be updating a file written by this class, replace
        // the date comment instead of adding a new one and preserving
        // the one written last time
        if (totalLines > skipLines
            && logicalLines.get(skipLines) instanceof Comment) {
            try {
                DateUtils.parseDateFromHeader(logicalLines
                                              .get(skipLines)
                                              .toString().substring(1));
                skipLines++;
            } catch (final java.text.ParseException pe) {
                // not an existing date comment
            }
        }
        osw.write("#" + DateUtils.getDateForHeader() + LS);

        boolean writtenSep = false;
        for (final Iterator i = logicalLines.subList(skipLines, totalLines).iterator();
             i.hasNext();) {
            final LogicalLine line = (LogicalLine) i.next();
            if (line instanceof Pair) {
                if (((Pair)line).isNew()) {
                    if (!writtenSep) {
                        osw.write(LS);
                        writtenSep = true;
                    }
                }
                osw.write(line.toString() + LS);
            } else if (line != null) {
                osw.write(line.toString() + LS);
            }
        }
        osw.close();
    }

    /**
     * Reads a properties file into an internally maintained
     * collection of logical lines (possibly spanning physical lines),
     * which make up the comments, blank lines and properties of the
     * file.
     * @param is the stream from which to read the data
     */
    private String readLines(final InputStream is) throws IOException {
        final InputStreamReader isr = new InputStreamReader(is, ResourceUtils.ISO_8859_1);
        final PushbackReader pbr = new PushbackReader(isr, 1);

        if (logicalLines.size() > 0) {
            // we add a blank line for spacing
            logicalLines.add(new Blank());
        }

        String s = readFirstLine(pbr);
        final BufferedReader br = new BufferedReader(pbr);

        boolean continuation = false;
        boolean comment = false;
        final StringBuffer fileBuffer = new StringBuffer();
        final StringBuffer logicalLineBuffer = new StringBuffer();
        while (s != null) {
            fileBuffer.append(s).append(LS);

            if (continuation) {
                // put in the line feed that was removed
                s = "\n" + s;
            } else {
                // could be a comment, if first non-whitespace is a # or !
                comment = s.matches("^( |\t|\f)*(#|!).*");
            }

            // continuation if not a comment and the line ends is an
            // odd number of backslashes
            if (!comment) {
                continuation = requiresContinuation(s);
            }

            logicalLineBuffer.append(s);

            if (!continuation) {
                LogicalLine line = null;
                if (comment) {
                    line = new Comment(logicalLineBuffer.toString());
                } else if (logicalLineBuffer.toString().trim().length() == 0) {
                    line = new Blank();
                } else {
                    line = new Pair(logicalLineBuffer.toString());
                    final String key = unescape(((Pair) line).getName());
                    if (keyedPairLines.containsKey(key)) {
                        // this key is already present, so we remove it and add
                        // the new one
                        remove(key);
                    }
                    keyedPairLines.put(key, Integer.valueOf(logicalLines.size()));
                }
                logicalLines.add(line);
                logicalLineBuffer.setLength(0);
            }
            s = br.readLine();
        }
        return fileBuffer.toString();
    }

    /**
     * Reads the first line and determines the EOL-style of the file
     * (relies on the style to be consistent, of course).
     *
     * <p>Sets LS as a side-effect.</p>
     *
     * @return the first line without any line separator, leaves the
     * reader positioned after the first line separator
     *
     * @since Ant 1.8.2
     */
    private String readFirstLine(final PushbackReader r) throws IOException {
        final StringBuffer sb = new StringBuffer(80);
        int ch = r.read();
        boolean hasCR = false;
        // when reaching EOF before the first EOL, assume native line
        // feeds
        LS = StringUtils.LINE_SEP;

        while (ch >= 0) {
            if (hasCR && ch != '\n') {
                // line feed is sole CR
                r.unread(ch);
                break;
            }

            if (ch == '\r') {
                LS = "\r";
                hasCR = true;
            } else if (ch == '\n') {
                LS = hasCR ? "\r\n" : "\n";
                break;
            } else {
                sb.append((char) ch);
            }
            ch = r.read();
        }
        return sb.toString();
    }

    /**
     * Returns <code>true</code> if the line represented by
     * <code>s</code> is to be continued on the next line of the file,
     * or <code>false</code> otherwise.
     * @param s the contents of the line to examine
     * @return <code>true</code> if the line is to be continued,
     * <code>false</code> otherwise
     */
    private boolean requiresContinuation(final String s) {
        final char[] ca = s.toCharArray();
        int i = ca.length - 1;
        while (i > 0 && ca[i] == '\\') {
            i--;
        }
        // trailing backslashes
        final int tb = ca.length - i - 1;
        return tb % 2 == 1;
    }

    /**
     * Unescape the string according to the rules for a Properties
     * file, as laid out in the docs for <a
     * href="http://java.sun.com/j2se/1.3/docs/api/java/util/Properties.html">java.util.Properties</a>.
     * @param s the string to unescape (coming from the source file)
     * @return the unescaped string
     */
    private String unescape(final String s) {
        /*
         * The following combinations are converted:
         * \n  newline
         * \r  carriage return
         * \f  form feed
         * \t  tab
         * \\  backslash
         * \u0000  unicode character
         * Any other slash is ignored, so
         * \b  becomes 'b'.
         */

        final char[] ch = new char[s.length() + 1];
        s.getChars(0, s.length(), ch, 0);
        ch[s.length()] = '\n';
        final StringBuffer buffy = new StringBuffer(s.length());
        for (int i = 0; i < ch.length; i++) {
            char c = ch[i];
            if (c == '\n') {
                // we have hit out end-of-string marker
                break;
            } else if (c == '\\') {
                // possibly an escape sequence
                c = ch[++i];
                if (c == 'n') {
                    buffy.append('\n');
                } else if (c == 'r') {
                    buffy.append('\r');
                } else if (c == 'f') {
                    buffy.append('\f');
                } else if (c == 't') {
                    buffy.append('\t');
                } else if (c == 'u') {
                    // handle unicode escapes
                    c = unescapeUnicode(ch, i + 1);
                    i += 4;
                    buffy.append(c);
                } else {
                    buffy.append(c);
                }
            } else {
                buffy.append(c);
            }
        }
        return buffy.toString();
    }

    /**
     * Retrieve the unicode character whose code is listed at position
     * <code>i</code> in the character array <code>ch</code>.
     * @param ch the character array containing the unicode character code
     * @return the character extracted
     */
    private char unescapeUnicode(final char[] ch, final int i) {
        final String s = new String(ch, i, 4);
        return (char) Integer.parseInt(s, 16);
    }

    /**
     * Escape the string <code>s</code> according to the rules in the
     * docs for <a
     * href="http://java.sun.com/j2se/1.3/docs/api/java/util/Properties.html">java.util.Properties</a>.
     * @param s the string to escape
     * @return the escaped string
     */
    private String escapeValue(final String s) {
        return escape(s, false);
    }

    /**
     * Escape the string <code>s</code> according to the rules in the
     * docs for <a
     * href="http://java.sun.com/j2se/1.3/docs/api/java/util/Properties.html">java.util.Properties</a>.
     * This method escapes all the whitespace, not just the stuff at
     * the beginning.
     * @param s the string to escape
     * @return the escaped string
     */
    private String escapeName(final String s) {
        return escape(s, true);
    }

    /**
     * Escape the string <code>s</code> according to the rules in the
     * docs for <a
     * href="http://java.sun.com/j2se/1.3/docs/api/java/util/Properties.html">java.util.Properties</a>.
     * @param s the string to escape
     * @param escapeAllSpaces if <code>true</code> the method escapes
     * all the spaces, if <code>false</code>, it escapes only the
     * leading whitespace
     * @return the escaped string
     */
    private String escape(final String s, final boolean escapeAllSpaces) {
        if (s == null) {
            return null;
        }

        final char[] ch = new char[s.length()];
        s.getChars(0, s.length(), ch, 0);
        final String forEscaping = "\t\f\r\n\\:=#!";
        final String escaped = "tfrn\\:=#!";
        final StringBuffer buffy = new StringBuffer(s.length());
        boolean leadingSpace = true;
        for (final char c : ch) {
            if (c == ' ') {
                if (escapeAllSpaces || leadingSpace) {
                    buffy.append("\\");
                }
            } else {
                leadingSpace = false;
            }
            final int p = forEscaping.indexOf(c);
            if (p != -1) {
                buffy.append("\\").append(escaped.substring(p, p + 1));
            } else if (c < 0x0020 || c > 0x007e) {
                buffy.append(escapeUnicode(c));
            } else {
                buffy.append(c);
            }
        }
        return buffy.toString();
    }

    /**
     * Return the unicode escape sequence for a character, in the form
     * \u005CuNNNN.
     * @param ch the character to encode
     * @return the unicode escape sequence
     */
    private String escapeUnicode(final char ch) {
        return "\\" + UnicodeUtil.EscapeUnicode(ch);
        }

    /**
     * Remove the comments in the leading up the {@link #logicalLines}
     * list leading up to line <code>pos</code>.
     * @param pos the line number to which the comments lead
     */
    private void removeCommentsEndingAt(int pos) {
        /* We want to remove comments preceding this position. Step
         * back counting blank lines (call this range B1) until we hit
         * something non-blank. If what we hit is not a comment, then
         * exit. If what we hit is a comment, then step back counting
         * comment lines (call this range C1). Nullify lines in C1 and
         * B1.
         */

        final int end = pos - 1;

        // step pos back until it hits something non-blank
        for (pos = end; pos > 0; pos--) {
            if (!(logicalLines.get(pos) instanceof Blank)) {
                break;
            }
        }

        // if the thing it hits is not a comment, then we have nothing
        // to remove
        if (!(logicalLines.get(pos) instanceof Comment)) {
            return;
        }

        // step back until we hit the start of the comment
        for (; pos >= 0; pos--) {
            if (!(logicalLines.get(pos) instanceof Comment)) {
                break;
            }
        }

        // now we want to delete from pos+1 to end
        for (pos++; pos <= end; pos++) {
            logicalLines.set(pos, null);
        }
    }

    /**
     * A logical line of the properties input stream.
     */
    private abstract static class LogicalLine {
        private String text;

        public LogicalLine(final String text) {
            this.text = text;
        }

        public void setText(final String text) {
            this.text = text;
        }

        @Override
        public String toString() {
            return text;
        }
    }

    /**
     * A blank line of the input stream.
     */
    private static class Blank extends LogicalLine {
        public Blank() {
            super("");
        }
    }

    /**
     * A comment line of the input stream.
     */
    private class Comment extends LogicalLine {
        public Comment(final String text) {
            super(text);
        }
    }

    /**
     * A key-value pair from the input stream. This may span more than
     * one physical line, but it is constitues as a single logical
     * line.
     */
    private static class Pair extends LogicalLine implements Cloneable {
        private String name;
        private String value;
        private boolean added;

        public Pair(final String text) {
            super(text);
            parsePair(text);
        }

        public Pair(final String name, final String value) {
            this(name + "=" + value);
        }

        public String getName() {
            return name;
        }

        public String getValue() {
            return value;
        }

        public void setValue(final String value) {
            this.value = value;
            setText(name + "=" + value);
        }

        public boolean isNew() {
            return added;
        }

        public void setNew(final boolean val) {
            added = val;
        }

        @Override
        public Object clone() {
            Object dolly = null;
            try {
                dolly = super.clone();
            } catch (final CloneNotSupportedException e) {
                // should be fine
                e.printStackTrace(); //NOSONAR
            }
            return dolly;
        }

        private void parsePair(final String text) {
            // need to find first non-escaped '=', ':', '\t' or ' '.
            final int pos = findFirstSeparator(text);
            if (pos == -1) {
                // trim leading whitespace only
                name = text;
                value = null;
            } else {
                name = text.substring(0, pos);
                value = text.substring(pos + 1, text.length());
            }
            // trim leading whitespace only
            name = stripStart(name, " \t\f");
        }

        private String stripStart(final String s, final String chars) {
            if (s == null) {
                return null;
            }

            int i = 0;
            for (; i < s.length(); i++) {
                if (chars.indexOf(s.charAt(i)) == -1) {
                    break;
                }
            }
            if (i == s.length()) {
                return "";
            }
            return s.substring(i);
        }

        private int findFirstSeparator(String s) {
            // Replace double backslashes with underscores so that they don't
            // confuse us looking for '\t' or '\=', for example, but they also
            // don't change the position of other characters
            s = s.replaceAll("\\\\\\\\", "__");

            // Replace single backslashes followed by separators, so we don't
            // pick them up
            s = s.replaceAll("\\\\=", "__");
            s = s.replaceAll("\\\\:", "__");
            s = s.replaceAll("\\\\ ", "__");
            s = s.replaceAll("\\\\t", "__");

            // Now only the unescaped separators are left
            return indexOfAny(s, " :=\t");
        }

        private int indexOfAny(final String s, final String chars) {
            if (s == null || chars == null) {
                return -1;
            }

            int p = s.length() + 1;
            for (int i = 0; i < chars.length(); i++) {
                final int x = s.indexOf(chars.charAt(i));
                if (x != -1 && x < p) {
                    p = x;
                }
            }
            if (p == s.length() + 1) {
                return -1;
            }
            return p;
        }
    }
}
