package org.codehaus.jackson.node;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;

import org.codehaus.jackson.*;
import org.codehaus.jackson.map.SerializerProvider;
import org.codehaus.jackson.map.TypeSerializer;

/**
 * Node that maps to JSON Object structures in JSON content.
 */
public class ObjectNode
    extends ContainerNode
{
    protected LinkedHashMap<String, JsonNode> _children = null;

    public ObjectNode(JsonNodeFactory nc) { super(nc); }
    
    /*
    /**********************************************************
    /* Implementation of core JsonNode API
    /**********************************************************
     */

    @Override public JsonToken asToken() { return JsonToken.START_OBJECT; }

    @Override
    public boolean isObject() { return true; }

    @Override
    public int size() {
        return (_children == null) ? 0 : _children.size();
    }

    @Override
    public Iterator<JsonNode> getElements()
    {
        return (_children == null) ? NoNodesIterator.instance() : _children.values().iterator();
    }

    @Override
    public JsonNode get(int index) { return null; }

    @Override
    public JsonNode get(String fieldName)
    {
        if (_children != null) {
            return _children.get(fieldName);
        }
        return null;
    }

    @Override
    public Iterator<String> getFieldNames()
    {
        return (_children == null) ? NoStringsIterator.instance() : _children.keySet().iterator();
    }

    @Override
    public JsonNode path(int index)
    {
        return MissingNode.getInstance();
    }

    @Override
    public JsonNode path(String fieldName)
    {
        if (_children != null) {
            JsonNode n = _children.get(fieldName);
            if (n != null) {
                return n;
            }
        }
        return MissingNode.getInstance();
    }

    /**
     * Method to use for accessing all fields (with both names
     * and values) of this JSON Object.
     */
    @Override
    public Iterator<Map.Entry<String, JsonNode>> getFields()
    {
        if (_children == null) {
            return NoFieldsIterator.instance;
        }
        return _children.entrySet().iterator();
    }

    @Override
    public ObjectNode with(String propertyName)
    {
        if (_children == null) {
            _children = new LinkedHashMap<String, JsonNode>();
        } else {
            JsonNode n = _children.get(propertyName);
            if (n != null) {
                if (n instanceof ObjectNode) {
                    return (ObjectNode) n;
                }
                throw new UnsupportedOperationException("Property '"+propertyName
                        +"' has value that is not of type ObjectNode (but "
                        +n.getClass().getName()+")");
            }
        }
        ObjectNode result = objectNode();
        _children.put(propertyName, result);
        return result;
    }
    
    /*
    /**********************************************************
    /* Public API, finding value nodes
    /**********************************************************
     */
    
    @Override
    public JsonNode findValue(String fieldName)
    {
        if (_children != null) {
            for (Map.Entry<String, JsonNode> entry : _children.entrySet()) {
                if (fieldName.equals(entry.getKey())) {
                    return entry.getValue();
                }
                JsonNode value = entry.getValue().findValue(fieldName);
                if (value != null) {
                    return value;
                }
            }
        }
        return null;
    }
    
    @Override
    public List<JsonNode> findValues(String fieldName, List<JsonNode> foundSoFar)
    {
        if (_children != null) {
            for (Map.Entry<String, JsonNode> entry : _children.entrySet()) {
                if (fieldName.equals(entry.getKey())) {
                    if (foundSoFar == null) {
                        foundSoFar = new ArrayList<JsonNode>();
                    }
                    foundSoFar.add(entry.getValue());
                } else { // only add children if parent not added
                    foundSoFar = entry.getValue().findValues(fieldName, foundSoFar);
                }
            }
        }
        return foundSoFar;
    }

    @Override
    public List<String> findValuesAsText(String fieldName, List<String> foundSoFar)
    {
        if (_children != null) {
            for (Map.Entry<String, JsonNode> entry : _children.entrySet()) {
                if (fieldName.equals(entry.getKey())) {
                    if (foundSoFar == null) {
                        foundSoFar = new ArrayList<String>();
                    }
                    foundSoFar.add(entry.getValue().asText());
                } else { // only add children if parent not added
                    foundSoFar = entry.getValue().findValuesAsText(fieldName, foundSoFar);
                }
            }
        }
        return foundSoFar;
    }
    
    @Override
    public ObjectNode findParent(String fieldName)
    {
        if (_children != null) {
            for (Map.Entry<String, JsonNode> entry : _children.entrySet()) {
                if (fieldName.equals(entry.getKey())) {
                    return this;
                }
                JsonNode value = entry.getValue().findParent(fieldName);
                if (value != null) {
                    return (ObjectNode) value;
                }
            }
        }
        return null;
    }

    @Override
    public List<JsonNode> findParents(String fieldName, List<JsonNode> foundSoFar)
    {
        if (_children != null) {
            for (Map.Entry<String, JsonNode> entry : _children.entrySet()) {
                if (fieldName.equals(entry.getKey())) {
                    if (foundSoFar == null) {
                        foundSoFar = new ArrayList<JsonNode>();
                    }
                    foundSoFar.add(this);
                } else { // only add children if parent not added
                    foundSoFar = entry.getValue().findParents(fieldName, foundSoFar);
                }
            }
        }
        return foundSoFar;
    }
    
    /*
    /**********************************************************
    /* Public API, serialization
    /**********************************************************
     */

    /**
     * Method that can be called to serialize this node and
     * all of its descendants using specified JSON generator.
     */
    @Override
    public final void serialize(JsonGenerator jg, SerializerProvider provider)
        throws IOException, JsonProcessingException
    {
        jg.writeStartObject();
        if (_children != null) {
            for (Map.Entry<String, JsonNode> en : _children.entrySet()) {
                jg.writeFieldName(en.getKey());
                /* 17-Feb-2009, tatu: Can we trust that all nodes will always
                 *   extend BaseJsonNode? Or if not, at least implement
                 *   JsonSerializable? Let's start with former, change if
                 *   we must.
                 */
                ((BaseJsonNode) en.getValue()).serialize(jg, provider);
            }
        }
        jg.writeEndObject();
    }

    @Override
    public void serializeWithType(JsonGenerator jg, SerializerProvider provider,
            TypeSerializer typeSer)
        throws IOException, JsonProcessingException
    {
        typeSer.writeTypePrefixForObject(this, jg);
        if (_children != null) {
            for (Map.Entry<String, JsonNode> en : _children.entrySet()) {
                jg.writeFieldName(en.getKey());
                ((BaseJsonNode) en.getValue()).serialize(jg, provider);
            }
        }
        typeSer.writeTypeSuffixForObject(this, jg);
    }

    /*
    /**********************************************************
    /* Extended ObjectNode API, mutators, generic
    /**********************************************************
     */

    /**
     * Method that will set specified field, replacing old value,
     * if any.
     *
     * @param value to set field to; if null, will be converted
     *   to a {@link NullNode} first  (to remove field entry, call
     *   {@link #remove} instead)
     *
     * @return Old value of the field, if any; null if there was no
     *   old value.
     */
    public JsonNode put(String fieldName, JsonNode value)
    {
        if (value == null) { // let's not store 'raw' nulls but nodes
            value = nullNode();
        }
        return _put(fieldName, value);
    }

    /**
     * Method for removing field entry from this ObjectNode.
     * Will return value of the field, if such field existed;
     * null if not.
     */
    public JsonNode remove(String fieldName)
    {
        if (_children != null) {
            return _children.remove(fieldName);
        }
        return null;
    }

    /**
     * Method for removing specified field properties out of
     * this ObjectNode.
     * 
     * @param fieldNames Names of fields to remove
     * 
     * @return This ObjectNode after removing entries
     * 
     * @since 1.6
     */
    public ObjectNode remove(Collection<String> fieldNames)
    {
        if (_children != null) {
            for (String fieldName : fieldNames) {
                _children.remove(fieldName);
            }
        }
        return this;
    }
    
    /**
     * Method for removing all field properties, such that this
     * ObjectNode will contain no properties after call.
     */
    @Override
    public ObjectNode removeAll()
    {
        _children = null;
        return this;
    }

    /**
     * Method for adding given properties to this object node, overriding
     * any existing values for those properties.
     * 
     * @param properties Properties to add
     * 
     * @return This node (to allow chaining)
     * 
     * @since 1.3
     */
    public JsonNode putAll(Map<String,JsonNode> properties)
    {
        if (_children == null) {
            _children = new LinkedHashMap<String, JsonNode>(properties);
        } else {
            for (Map.Entry<String, JsonNode> en : properties.entrySet()) {
                JsonNode n = en.getValue();
                if (n == null) {
                    n = nullNode();
                }
                _children.put(en.getKey(), n);
            }
        }
        return this;
    }

    /**
     * Method for adding all properties of the given Object, overriding
     * any existing values for those properties.
     * 
     * @param other Object of which properties to add to this object
     * 
     * @return This node (to allow chaining)
     * 
     * @since 1.3
     */
    public JsonNode putAll(ObjectNode other)
    {
        int len = other.size();
        if (len > 0) {
            if (_children == null) {
                _children = new LinkedHashMap<String, JsonNode>(len);
            }
            other.putContentsTo(_children);
        }
        return this;
    }

    /**
     * Method for removing all field properties out of this ObjectNode
     * <b>except</b> for ones specified in argument.
     * 
     * @param fieldNames Fields to <b>retain</b> in this ObjectNode
     * 
     * @return This ObjectNode (to allow call chaining)
     * 
     * @since 1.6
     */
    public ObjectNode retain(Collection<String> fieldNames)
    {
        if (_children != null) {
            Iterator<Map.Entry<String,JsonNode>> entries = _children.entrySet().iterator();
            while (entries.hasNext()) {
                Map.Entry<String, JsonNode> entry = entries.next();
                if (!fieldNames.contains(entry.getKey())) {
                    entries.remove();
                }
            }
        }
        return this;
    }

    /**
     * Method for removing all field properties out of this ObjectNode
     * <b>except</b> for ones specified in argument.
     * 
     * @param fieldNames Fields to <b>retain</b> in this ObjectNode
     * 
     * @return This ObjectNode (to allow call chaining)
     * 
     * @since 1.6
     */
    public ObjectNode retain(String... fieldNames) {
        return retain(Arrays.asList(fieldNames));
    }
    
    /*
    /**********************************************************
    /* Extended ObjectNode API, mutators, typed
    /**********************************************************
     */

    /**
     * Method that will construct an ArrayNode and add it as a
     * field of this ObjectNode, replacing old value, if any.
     *
     * @return Newly constructed ArrayNode (NOT the old value,
     *   which could be of any type)
     */
    public ArrayNode putArray(String fieldName)
    {
        ArrayNode n  = arrayNode();
        _put(fieldName, n);
        return n;
    }

    /**
     * Method that will construct an ObjectNode and add it as a
     * field of this ObjectNode, replacing old value, if any.
     *
     * @return Newly constructed ObjectNode (NOT the old value,
     *   which could be of any type)
     */
    public ObjectNode putObject(String fieldName)
    {
        ObjectNode n  = objectNode();
        _put(fieldName, n);
        return n;
    }

    public void putPOJO(String fieldName, Object pojo)
    {
        _put(fieldName, POJONode(pojo));
    }

    public void putNull(String fieldName)
    {
        _put(fieldName, nullNode());
    }

    /**
     * Method for setting value of a field to specified numeric value.
     */
    public void put(String fieldName, int v) { _put(fieldName, numberNode(v)); }

    /**
     * Alternative method that we need to avoid bumping into NPE issues
     * with auto-unboxing.
     * 
     * @since 1.9
     */
    public void put(String fieldName, Integer value) {
        if (value == null) {
            _put(fieldName, nullNode());
        } else {
            _put(fieldName, numberNode(value.intValue()));
        }
    }
    
    /**
     * Method for setting value of a field to specified numeric value.
     */
    public void put(String fieldName, long v) { _put(fieldName, numberNode(v)); }

    /**
     * Alternative method that we need to avoid bumping into NPE issues
     * with auto-unboxing.
     * 
     * @since 1.9
     */
    public void put(String fieldName, Long value) {
        if (value == null) {
            _put(fieldName, nullNode());
        } else {
            _put(fieldName, numberNode(value.longValue()));
        }
    }
    
    /**
     * Method for setting value of a field to specified numeric value.
     */
    public void put(String fieldName, float v) { _put(fieldName, numberNode(v)); }

    /**
     * Alternative method that we need to avoid bumping into NPE issues
     * with auto-unboxing.
     * 
     * @since 1.9
     */
    public void put(String fieldName, Float value) {
        if (value == null) {
            _put(fieldName, nullNode());
        } else {
            _put(fieldName, numberNode(value.floatValue()));
        }
    }
    
    /**
     * Method for setting value of a field to specified numeric value.
     */
    public void put(String fieldName, double v) { _put(fieldName, numberNode(v)); }

    /**
     * Alternative method that we need to avoid bumping into NPE issues
     * with auto-unboxing.
     * 
     * @since 1.9
     */
    public void put(String fieldName, Double value) {
        if (value == null) {
            _put(fieldName, nullNode());
        } else {
            _put(fieldName, numberNode(value.doubleValue()));
        }
    }
    
    /**
     * Method for setting value of a field to specified numeric value.
     */
    public void put(String fieldName, BigDecimal v) {
        if (v == null) {
            putNull(fieldName);
        } else {
            _put(fieldName, numberNode(v));
        }
    }

    /**
     * Method for setting value of a field to specified String value.
     */
    public void put(String fieldName, String v) {
        if (v == null) {
            putNull(fieldName);
        } else {
            _put(fieldName, textNode(v));
        }
    }

    /**
     * Method for setting value of a field to specified String value.
     */
    public void put(String fieldName, boolean v) { _put(fieldName, booleanNode(v)); }

    /**
     * Alternative method that we need to avoid bumping into NPE issues
     * with auto-unboxing.
     * 
     * @since 1.9
     */
    public void put(String fieldName, Boolean value) {
        if (value == null) {
            _put(fieldName, nullNode());
        } else {
            _put(fieldName, booleanNode(value.booleanValue()));
        }
    }
    
    /**
     * Method for setting value of a field to specified binary value
     */
    public void put(String fieldName, byte[] v) {
        if (v == null) {
            _put(fieldName, nullNode());
        } else {
            _put(fieldName, binaryNode(v));
        }
    }

    /*
    /**********************************************************
    /* Package methods (for other node classes to use)
    /**********************************************************
     */

    /**
     * @since 1.6
     */
    protected void putContentsTo(Map<String,JsonNode> dst)
    {
        if (_children != null) {
            for (Map.Entry<String,JsonNode> en : _children.entrySet()) {
                dst.put(en.getKey(), en.getValue());
            }
        }
    }

    /*
    /**********************************************************
    /* Standard methods
    /**********************************************************
     */

    @Override
    public boolean equals(Object o)
    {
        if (o == this) return true;
        if (o == null) return false;
        if (o.getClass() != getClass()) {
            return false;
        }
        ObjectNode other = (ObjectNode) o;
        if (other.size() != size()) {
            return false;
        }
        if (_children != null) {
            for (Map.Entry<String, JsonNode> en : _children.entrySet()) {
                String key = en.getKey();
                JsonNode value = en.getValue();

                JsonNode otherValue = other.get(key);

                if (otherValue == null || !otherValue.equals(value)) {
                    return false;
                }
            }
        }
        return true;
    }

    @Override
    public int hashCode()
    {
        return (_children == null) ? -1 : _children.hashCode();
    }

    @Override
    public String toString()
    {
        StringBuilder sb = new StringBuilder(32 + (size() << 4));
        sb.append("{");
        if (_children != null) {
            int count = 0;
            for (Map.Entry<String, JsonNode> en : _children.entrySet()) {
                if (count > 0) {
                    sb.append(",");
                }
                ++count;
                TextNode.appendQuoted(sb, en.getKey());
                sb.append(':');
                sb.append(en.getValue().toString());
            }
        }
        sb.append("}");
        return sb.toString();
    }

    /*
    /**********************************************************
    /* Internal methods
    /**********************************************************
     */

    private final JsonNode _put(String fieldName, JsonNode value)
    {
        if (_children == null) {
            _children = new LinkedHashMap<String, JsonNode>();
        }
        return _children.put(fieldName, value);
    }

    /*
    /**********************************************************
    /* Helper classes
    /**********************************************************
     */

    /**
     * For efficiency, let's share the "no fields" iterator...
     */
    protected static class NoFieldsIterator
        implements Iterator<Map.Entry<String, JsonNode>>
    {
        final static NoFieldsIterator instance = new NoFieldsIterator();

        private NoFieldsIterator() { }

        @Override
        public boolean hasNext() { return false; }
        @Override
        public Map.Entry<String,JsonNode> next() { throw new NoSuchElementException(); }

        @Override
        public void remove() { // or IllegalOperationException?
            throw new IllegalStateException();
        }
    }
}
