/*
 * 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.netbeans.modules.properties;


import java.beans.*;
import java.io.*;
import javax.swing.text.BadLocationException;

import org.openide.nodes.Node;
import org.openide.ErrorManager;
import org.openide.text.PositionBounds;


/**
 * Base class for representations of elements in properties files.
 *
 * @author Petr Jiricka
 * @author Petr Kuzel - moved to nonescaped strings level
 * //!!! why is it serializable?
 */
public abstract class Element implements Serializable {

    /** Property change support */
    private transient PropertyChangeSupport support = new PropertyChangeSupport(this);

    /** Position of the begin and the end of the element. Could
     * be null indicating the element is not part of properties structure yet. */
    protected PositionBounds bounds;

    
    /** Create a new element. */
    protected Element(PositionBounds bounds) {
        this.bounds = bounds;
    }

    
    /** Getter for bounds property. */
    public PositionBounds getBounds() {
        return bounds;
    }

    /**
     * Updates the element fields. This method is called after reparsing.
     * @param elem the element to merge with
     */
    void update(Element elem) {
        this.bounds = elem.bounds;
    }

    /** Fires property change event.
     * @param name property name
     * @param o old value
     * @param n new value
     */
    protected final void firePropertyChange(String name, Object o, Object n) {
        support.firePropertyChange (name, o, n);
    }

    /** Adds property listener */
    public void addPropertyChangeListener (PropertyChangeListener l) {
        support.addPropertyChangeListener (l);
    }

    /** Removes property listener */
    public void removePropertyChangeListener (PropertyChangeListener l) {
        support.removePropertyChangeListener (l);
    }

    /** Prints this element (and all its subelements) by calling <code>bounds.setText(...)</code>
     * If <code>bounds</code> is null does nothing. 
     * @see #bounds */
    public final void print() {
        if (bounds == null) {
            return;
        }
        try {
            bounds.setText(getDocumentString());
        } catch (BadLocationException e) {
            ErrorManager.getDefault().notify(e);
        } catch (IOException e) {
            ErrorManager.getDefault().notify(e);
        }
    }

    /**
     * Get a string representation of the element for printing into Document.
     * It currently means that it's properly escaped.
     * @return the string in its Document form
     */
    public abstract String getDocumentString();

    /**
     * Get debug string of the element.
     * @return the string
     */
    public String toString() {
        if (bounds == null) {
            return "(no bounds)";
        }
        return new StringBuffer(16)
                .append('(')
                .append(bounds.getBegin().getOffset())
                .append(", ")                                           //NOI18N
                .append(bounds.getEnd().getOffset())
                .append(')')
                .toString();
    }

    
    /** General class for basic elements, which contain value directly. */
    public static abstract class Basic extends Element {

        private static final String hexaDigitChars
                                    = "0123456789abcdefABCDEF";         //NOI18N

        protected static void appendIsoControlChar(final StringBuilder buf,
                                                   final char c) {
            switch (c) {
            case '\t':
                buf.append('\\').append('t');
                break;
            case '\n':
                buf.append('\\').append('n');
                break;
            case '\f':
                buf.append('\\').append('f');
                break;
            case '\r':
                buf.append('\\').append('r');
                break;
            default:
                buf.append('\\').append('u');
                for (int shift = 12; shift >= 0; shift -= 4) {
                    buf.append(hexaDigitChars.charAt(
                                    ((c >> shift) & 0xf)));
                }
            }
        }

        /** Parsed value of the element */
        protected String value;

        /** Create a new basic element. */
        protected Basic(PositionBounds bounds, String value) {
            super(bounds);
            this.value = value;
        }

        /**
         * Updates the element fields. This method is called after reparsing.
         * @param elem elemnet to merge with
         */
        void update(Element elem) {
            super.update(elem);
            this.value = ((Basic)elem).value;
        }

        /** Get a string representation of the element.
         * @return the string + bounds
         */
        public String toString() {
            return value + "   " + super.toString(); // NOI18N
        }

        /**
         * Get a value of the element.
         * @return the Java string (no escaping)
         */
        public String getValue() {
            return value;
        }

        /**
         * Sets the value. Does not check if the value has changed.
         * The value is immediately propadated in text Document possibly
         * triggering DocumentEvents.
         * @param value Java string (no escaping)
         */
        public void setValue(String value) {
            this.value = value;
            this.print();
        }

        @Override
        public boolean equals(Object anObject) {
            if(this == anObject) {
                return true;
            }
            if(anObject instanceof Basic) {
                Basic b = (Basic)anObject;
                if(value == null) {
                    return b.value == null;
                }
                return value.equals(b.value);
            }
            return false;
        }

    } // End of nested class Basic.


    /** Class representing key element in properties file. */
    public static class KeyElem extends Basic {

        /** Generated serial version UID. */
        static final long serialVersionUID =6828294289485744331L;
        
        
        /** Create a new key element. */
        protected KeyElem(PositionBounds bounds, String value) {
            super(bounds, value);
        }

        
        /** Get a string representation of the key for printing. Treats the '=' sign as a part of the key
        * @return the string
        */
        public String getDocumentString() {
            return escapeSpecialChars(value) + "=";                     //NOI18N
        }

        /**
         * 
         * @author  Marian Petras
         */
        private static final String escapeSpecialChars(final String text) {
            StringBuilder buf = new StringBuilder(text.length() + 16);

            final int length = text.length();
            for (int i = 0; i < length; i++) {
                char c = text.charAt(i);
                if (c < 0x20) {
                    Basic.appendIsoControlChar(buf, c);
                } else {
                    switch (c) {
                    case '#':
                    case '!':
                        if (i == 0) {
                            buf.append('\\');
                        }
                        break;
                    case ' ':
                    case '=':
                    case ':':
                    case '\\':
                        buf.append('\\');
                        break;
                    }
                    buf.append(c);
                }
            }
            return buf.toString();
        }

        @Override
        public boolean equals(Object anObject) {
            return anObject instanceof KeyElem && super.equals(anObject);
        }

    } // End of nested class KeyElem.
    

    /** Class representing value element in properties files. */
    public static class ValueElem extends Basic {

        /** Generated serial version UID. */
        static final long serialVersionUID =4662649023463958853L;
        
        /** Create a new value element. */
        protected ValueElem(PositionBounds bounds, String value) {
            super(bounds, value);
        }

        /** Get a string representation of the value for printing. Appends end of the line after the value.
        * @return the string
        */
        public String getDocumentString() {
            // escape outerspaces and continious line marks
            return escapeSpecialChars(value) + "\n";                    //NOI18N
        }

        /**
         * 
         * @author  Marian Petras
         */
        private static final String escapeSpecialChars(final String text) {
            StringBuilder buf = new StringBuilder(text.length() + 16);

            boolean isInitialWhitespace = true;
            final int length = text.length();
            for (int i = 0; i < length; i++) {
                char c = text.charAt(i);

                boolean escape = false;
                if (c == '\\') {
                    isInitialWhitespace = false;
                    escape = true;
                } else if (isInitialWhitespace) {
                    if (c == ' ') {
                        escape = true;
                    } else {
                        isInitialWhitespace =    (c == '\t') || (c == '\r')
                                              || (c == '\n') || (c == '\f');
                    }
                }

                if (c < 0x20) {
                    Basic.appendIsoControlChar(buf, c);
                } else {
                    if (escape) {
                        buf.append('\\');
                    }
                    buf.append(c);
                }
            }
            return buf.toString();
        }

    } // End of nested class ValueElem.

    /**
     * Class representing comment element in properties files. <code>null</code> values of the
     * string are legal and indicate that the comment is empty. It should contain
     * pure comment string without comment markers.
     */
    public static class CommentElem extends Basic {

        /** Genererated serial version UID. */
        static final long serialVersionUID =2418308580934815756L;
        
        
        /**
         * Create a new comment element.
         * @param value Comment without its markers (leading '#' or '!'). Markers
         *        are automatically prepended while writing it down to Document.
         */
        protected CommentElem(PositionBounds bounds, String value) {
            super(bounds, value);
        }

        
        /** Get a string representation of the comment for printing. Makes sure every non-empty line starts with a # and
        * that the last line is terminated with an end of line marker.
        * @return the string
        */
        public String getDocumentString() {
            if (value == null || value.length() == 0)
                return ""; // NOI18N
            else {
                // insert #s at the beginning of the lines which contain non-blank characters
                // holds the last position where we might have to insert a # if this line contains non-blanks
                StringBuffer sb = new StringBuffer(value);
                // append the \n if missing
                if (sb.charAt(sb.length() - 1) != '\n') {
                    sb.append('\n');
                }
                int lineStart = 0;
                boolean hasCommentChar = false;
                for (int i=0; i<sb.length(); i++) {
                    char aChar = sb.charAt(i);
                    // new line
                    if (aChar == '\n') {
                        String line = sb.substring(lineStart, i);
                        String convertedLine = escapeSpecialChars(line);
                        sb.replace(lineStart, i, convertedLine);

                        // shift the index:
                        i += convertedLine.length() - line.length();

                        // the next line starts after \n:
                        lineStart = i + 1;

                        hasCommentChar = false;
                    } else if (!hasCommentChar
                          && UtilConvert.whiteSpaceChars.indexOf(aChar) == -1) {
                        // nonempty symbol
                        if ((aChar == '#') || (aChar == '!')) {
                            lineStart = i + 1;
                        } else {
                            // insert a #
                            sb.insert(lineStart, '#');
                            i++;
                            lineStart = i;
                        }
                        hasCommentChar = true;
                    }
                }
                return sb.toString();
            }
        }

        /**
         *
         * @author  Marian Petras
         */
        private static final String escapeSpecialChars(final String text) {
            StringBuilder buf = new StringBuilder(text.length() + 16);

            final int length = text.length();
            for (int i = 0; i < length; i++) {
                char c = text.charAt(i);
                assert (c != '\n');

                if ((c < 0x20) && (c != '\t')) { // keep tabs un-escaped in comments
                    Basic.appendIsoControlChar(buf, c);
                    continue;
                } else if (c == '\\') {
                    buf.append('\\');
                }
                buf.append(c);
            }
            return buf.toString();
        }

        @Override
        public boolean equals(Object anObject) {
            return anObject instanceof CommentElem && super.equals(anObject);
        }

    } // End of nested CommentElem.


    /** 
     * Class representing element in  properties file. Each element contains comment (preceding the property),
     * key and value subelement.
     */
    public static class ItemElem extends Element implements Node.Cookie {

        /** Key element.  */
        private KeyElem     key;
        
        /** Value element. */        
        private ValueElem   value;
        
        /** Comment element. */
        private CommentElem comment;
        
        /** Parent of this element - active element has a non-null parent. */
        private PropertiesStructure parent;

        /** Name of the Key property */
        public static final String PROP_ITEM_KEY     = "key"; // NOI18N
        /** Name of the Value property */
        public static final String PROP_ITEM_VALUE   = "value"; // NOI18N
        /** Name of the Comment property */
        public static final String PROP_ITEM_COMMENT = "comment"; // NOI18N

        /** Generated serial version UID. */
        static final long serialVersionUID =1078147817847520586L;

        
        /** Create a new basic element. <code>key</code> and <code>value</code> may be null. */
        protected ItemElem(PositionBounds bounds, KeyElem key, ValueElem value, CommentElem comment) {
            super(bounds);
            this.key     = key;
            this.value   = value;
            this.comment = comment;
        }

        
        /** Sets the parent of this element. */
        void setParent(PropertiesStructure ps) {
            parent = ps;
        }

        /** Gets parent.
         * @exception IllegalStateException if the parent is <code>null</code>. */
        private PropertiesStructure getParent() {
            if(parent == null) {
                throw new IllegalStateException("Resource Bundle: Parent is missing"); // NOI18N
            }

            return parent;
        }

        /** Get a value string of the element.
         * @return the string
         */
        public String toString() {
            return comment.toString() + "\n" + // NOI18N
                ((key   == null) ? "" : key.toString()) + "\n" + // NOI18N
                ((value == null) ? "" : value.toString()) + "\n"; // NOI18N
        }

        /** Returns the key element for this item. */
        public KeyElem getKeyElem() {
            return key;
        }

        /** Returns the value element for this item. */
        public ValueElem getValueElem() {
            return value;
        }

        /** Returns the comment element for this item. */
        public CommentElem getCommentElem() {
            return comment;
        }

        void update(Element elem) {
            super.update(elem);
            if (this.key == null)
                this.key     = ((ItemElem)elem).key;
            else
                this.key.update(((ItemElem)elem).key);

            if (this.value == null)
                this.value   = ((ItemElem)elem).value;
            else
                this.value.update(((ItemElem)elem).value);

            this.comment.update(((ItemElem)elem).comment);
        }

        public String getDocumentString() {
            return comment.getDocumentString() +
                ((key   == null) ? "" : key.getDocumentString()) + // NOI18N
                ((value == null) ? "" : value.getDocumentString()); // NOI18N
        }

        /** Get a key by which to identify this record
         * @return nonescaped key
         */
        public String getKey() {
            return (key == null) ? null : key.getValue();
        }

        /** Set the key for this item
        *  @param newKey nonescaped key
        */                        
        public void setKey(String newKey) {
            String oldKey = key.getValue();
            if (!oldKey.equals(newKey)) {
                key.setValue(newKey);
                getParent().itemKeyChanged(oldKey, this);
                this.firePropertyChange(PROP_ITEM_KEY, oldKey, newKey);
            }
        }

        /** Get the value of this item */
        public String getValue() {
            return (value == null) ? null : value.getValue();
        }

        /** Set the value of this item
         *  @param newValue the new value
         */                        
        public void setValue(String newValue) {
            String oldValue = value.getValue();
            if (!oldValue.equals(newValue)) {
                
                if(oldValue.equals("")) // NOI18N
                    // Reprint key for the case it's alone yet and doesn't have seprator after (= : or whitespace).
                    key.print();
                
                value.setValue(newValue);
                getParent().itemChanged(this);
                this.firePropertyChange(PROP_ITEM_VALUE, oldValue, newValue);
            }
        }

        /** Get the comment for this item */
        public String getComment() {
            return (comment == null) ? null : comment.getValue();
        }

        /** Set the comment for this item
         *  @param newComment the new comment (escaped value)
         *  //??? why is required escaped value? I'd expect escapng to be applied during
         *  writing value down to stream no earlier
         */                        
        public void setComment(String newComment) {
            String oldComment = comment.getValue();
            if ((oldComment == null && newComment != null) || (oldComment != null && !oldComment.equals(newComment))) {
                comment.setValue(newComment);
                getParent().itemChanged(this);
                this.firePropertyChange(PROP_ITEM_COMMENT, oldComment, newComment);
            }
        }

        /** Checks for equality of two ItemElem-s */
        public boolean equals(Object item) {
            if (item == null || !(item instanceof ItemElem))
                return false;
            ItemElem ie = (ItemElem)item;
            return isKeyEqual(ie) && isValueEqual(ie) && isCommentEqual(ie);
        }

        private boolean isKeyEqual(ItemElem ie) {
            if(key==null) {
                return ie.key==null;
            }
            return key.equals(ie.key);
        }

        private boolean isValueEqual(ItemElem ie) {
            if(value==null) {
                return ie.value==null;
            }
            return value.equals(ie.value);
        }

        private boolean isCommentEqual(ItemElem ie) {
            if(comment==null) {
                return ie.comment==null;
            }
            return comment.equals(ie.comment);
        }

    } // End of nested class ItemElem.
}
