/*
 * 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.io.*;
import java.util.Iterator;
import java.util.Map;
import java.util.HashMap;
import javax.swing.text.BadLocationException;

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


/**
 * Element structure for one .properties file tightly
 * bound with that file's document.
 *
 * @author Petr Jiricka
 */
public class PropertiesStructure extends Element {

    /**
     * Map&lt;<code>String</code> to <code>Element.ItemElem</code>&gt;.
     */
    private Map<String,Element.ItemElem> items;

    /** If active, contains link to its handler (parent) */
    private StructHandler handler;

    /** Generated serial version UID. */
    static final long serialVersionUID = -78380271920882131L;
    
    
    /** Constructs a new PropertiesStructure for the given bounds and items. */
    public PropertiesStructure(PositionBounds bounds, Map<String,Element.ItemElem> items) {
        super(bounds);
        // set this structure as a parent for all elements
        for (Element.ItemElem itemElem : items.values()) {
            itemElem.setParent(this);
        }
        this.items = items;
    }

    
    /** Updates the current structure by the new structure obtained by reparsing the document.
     * Looks for changes between the structures and according to them calls update methods.
     */
    public void update(PropertiesStructure struct) {
        synchronized(getParentBundleStructure()) {
        synchronized(getParent()) {
            boolean structChanged = false;
            Element.ItemElem oldItem;

            Map<String,Element.ItemElem> new_items = struct.items;
            Map<String,Element.ItemElem> changed  = new HashMap<String,Element.ItemElem>();
            Map<String,Element.ItemElem> inserted = new HashMap<String,Element.ItemElem>();
            Map<String,Element.ItemElem> deleted  = new HashMap<String,Element.ItemElem>();

            for (Element.ItemElem curItem : new_items.values()) {
                curItem.setParent(this);
                oldItem = getItem(curItem.getKey());
                if (oldItem == null) {
                    inserted.put(curItem.getKey(), curItem);
                } else {
                    if (!curItem.equals(oldItem)) {
                        changed.put(curItem.getKey(), curItem);
                    }
                    items.remove(oldItem.getKey());
                }
            }

            deleted = items;
            if ((deleted.size() > 0) || (inserted.size() > 0)) {
                structChanged = true;
            }
            // assign the new structure
            items = new_items;

            // Update bounds.
            this.bounds = struct.getBounds();
            
            // notification
            if (structChanged) {
                structureChanged(changed, inserted, deleted);
            } else {
                // notify about changes in all items
                for (Element.ItemElem itemElem : changed.values()) {
                    itemChanged(itemElem);
                }
            }
        }
        }
    }

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

    /** Gets parent for this properties structure. 
     * @return <code>StructureHandler</code> instance. */
    public StructHandler getParent() {
        if (handler == null) {
            throw new IllegalStateException();
        }
        return handler;
    }

    /** Gets bundle structure of bundles where this .properties file belongs to. */
    BundleStructure getParentBundleStructure() {
        PropertiesDataObject dataObj;
        dataObj = (PropertiesDataObject) getParent().getEntry().getDataObject();
        return dataObj.getBundleStructure();
    }

    /** Prints all structure to document.
     * @return the structure dump */
    public String getDocumentString() {
        StringBuilder sb = new StringBuilder();
        for (Element.ItemElem item : items.values()) {
            sb.append(item.getDocumentString());
        }
        
        return sb.toString();
    }

    /** Overrides superclass method.
     * @return the formatted structure dump */
    public String toString() {
        StringBuilder sb = new StringBuilder();
        for (Element.ItemElem item : items.values()) {
            sb.append(item.toString());
            sb.append("- - -\n");                                       //NOI18N
        }
        
        return sb.toString();
    }

    /**
     * Retrieves an item (property value) associated with the specified 
     * {@code key} (property name).
     * @param key Java string (unescaped).
     * @return an item or {@code null} if does not exist.
     */
    public Element.ItemElem getItem(String key) {
        return items.get(key);
    }

    /**
     * Renames an item.
     * @param oldKey nonescaped original name
     * @param newKey nonescaped new name
     * @return true if the item has been renamed successfully, false if another item with the same name exists.
     */                         
    public boolean renameItem(String oldKey, String newKey) {
        synchronized(getParentBundleStructure()) {
        synchronized(getParent()) {
            Element.ItemElem item = getItem(newKey);
            if (item == null) {
                item = getItem(oldKey);
                if (item == null) {
                    return false;
                }
                items.remove(oldKey);
                items.put(newKey, item);
                item.setKey(newKey); // fires itemKeyChanged()
                return true;
            }
            else {
                return false;
            }
        }
        }
    }

    /** Deletes an item from the structure, if exists.
     * @return <code>true<code> if the item has been deleted successfully, <code>false</code> otherwise */
    public boolean deleteItem(String key) {
        synchronized(getParentBundleStructure()) {
        synchronized(getParent()) {
            Element.ItemElem item = getItem(key);
            
            if (item == null) {
                return false;
            }
            try {
                item.getBounds().setText(""); // NOI18N
                items.remove(key);
                structureChanged();     //??? fired from under lock
                return true;
            } catch (IOException e) {
                ErrorManager.getDefault().notify(e);
                return false;
            } catch (BadLocationException e) {
                ErrorManager.getDefault().notify(e);
                return false;
            }
        }
        }
    }

    /**
     * Adds an item to the end of the file, or before the terminating comment,
     * if there is any.
     *
     * @return <code>true</code> if the item has been added successfully, 
     *         <code>false</code> otherwise.
     */
    public boolean addItem(String key, String value, String comment) {
        Element.ItemElem item = getItem(key);
        if (item != null) {
            return false;
        }
        // construct the new element
        item = new Element.ItemElem(null,
                                    new Element.KeyElem    (null, key),
                                    new Element.ValueElem  (null, value),
                                    new Element.CommentElem(null, comment));        
        // find the position where to add it
        try {
            synchronized(getParentBundleStructure()) {
            synchronized(getParent()) {
                PositionBounds pos = getBounds();
 
                PositionBounds itemBounds;
                if (pos.getText().endsWith("\n")) {
                    itemBounds = pos.insertAfter(item.getDocumentString()); 
                } else {
                    itemBounds = pos.insertAfter("\n").insertAfter(item.getDocumentString()); 
                }
                
                item.bounds = itemBounds;

                //#17044 update in-memory model
                item.setParent(this);
                items.put(key, item);  
                structureChanged();
                
                return true;
            }
            }
        } catch (IOException ioe) {
            return false;
        } catch (BadLocationException ble) {
            return false;
        }
    }

    /**
     * Adds the specified {@code item} to the end of the file, or before the
     * terminating comment, if there is any.
     *
     * @param item
     * @return <code>true</code> if the item has been added successfully,
     *         <code>false</code> otherwise
     */
    boolean addItem(Element.ItemElem item) {
        return addItem(item.getKey(), item.getValue(), item.getComment());
    }

    /** Returns iterator thropugh all items, including empty ones */
    public Iterator<Element.ItemElem> allItems() {
        return items.values().iterator();
    }

    /** Notification that the given item has changed (its value or comment) */
    void itemChanged(Element.ItemElem elem) {
        getParentBundleStructure().notifyItemChanged(this, elem);
    }

    /** Notification that the structure has changed (no specific information). */
    void structureChanged() {
        getParentBundleStructure().notifyOneFileChanged(getParent());
    }

    /** Notification that the structure has changed (items have been added or
     * deleted, also includes changing an item's key). */
    void structureChanged(Map<String,Element.ItemElem> changed,
                          Map<String,Element.ItemElem> inserted,
                          Map<String,Element.ItemElem> deleted) {
        getParentBundleStructure().notifyOneFileChanged(
                getParent(),
                changed,
                inserted,
                deleted);
    }

    /**
     * Notification that an item's key has changed. Subcase of structureChanged().
     * Think twice when using this - don't I need to reparse all files ?
     */
    void itemKeyChanged(String oldKey, Element.ItemElem newElem) {
        // structural change information - watch: there may be two properties of the same name !
        // maybe this is unnecessary
        Map<String,Element.ItemElem> changed  = new HashMap<String,Element.ItemElem>();
        Map<String,Element.ItemElem> inserted = new HashMap<String,Element.ItemElem>();
        Map<String,Element.ItemElem> deleted  = new HashMap<String,Element.ItemElem>();

        // old key
        Element.ItemElem item = getItem(oldKey);
        if (item == null) {
            // old key deleted
            Element.ItemElem emptyItem = new Element.ItemElem(
                    null,
                    new Element.KeyElem(null, oldKey),
                    new Element.ValueElem(null, ""),                    //NOI18N
                    new Element.CommentElem(null, ""));                 //NOI18N
            deleted.put(oldKey, emptyItem);
        } else {
            // old key changed
            changed.put(item.getKey(), item);
        }
        // new key
        inserted.put(newElem.getKey(), newElem);

        structureChanged(changed, inserted, deleted);
    }
}
