/*
 * Protocol Buffers - Google's data interchange format
 * Copyright 2014 Google Inc.  All rights reserved.
 * https://developers.google.com/protocol-buffers/
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.google.protobuf.jruby;

import com.google.protobuf.Descriptors;
import com.google.protobuf.DynamicMessage;
import com.google.protobuf.MapEntry;
import org.jruby.*;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.internal.runtime.methods.DynamicMethod;
import org.jruby.runtime.Block;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.ByteList;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@JRubyClass(name = "Map", include = "Enumerable")
public class RubyMap extends RubyObject {
    public static void createRubyMap(Ruby runtime) {
        RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf");
        RubyClass cMap = protobuf.defineClassUnder("Map", runtime.getObject(), new ObjectAllocator() {
            @Override
            public IRubyObject allocate(Ruby ruby, RubyClass rubyClass) {
                return new RubyMap(ruby, rubyClass);
            }
        });
        cMap.includeModule(runtime.getEnumerable());
        cMap.defineAnnotatedMethods(RubyMap.class);
    }

    public RubyMap(Ruby ruby, RubyClass rubyClass) {
        super(ruby, rubyClass);
    }

    /*
     * call-seq:
     *     Map.new(key_type, value_type, value_typeclass = nil, init_hashmap = {})
     *     => new map
     *
     * Allocates a new Map container. This constructor may be called with 2, 3, or 4
     * arguments. The first two arguments are always present and are symbols (taking
     * on the same values as field-type symbols in message descriptors) that
     * indicate the type of the map key and value fields.
     *
     * The supported key types are: :int32, :int64, :uint32, :uint64, :bool,
     * :string, :bytes.
     *
     * The supported value types are: :int32, :int64, :uint32, :uint64, :bool,
     * :string, :bytes, :enum, :message.
     *
     * The third argument, value_typeclass, must be present if value_type is :enum
     * or :message. As in RepeatedField#new, this argument must be a message class
     * (for :message) or enum module (for :enum).
     *
     * The last argument, if present, provides initial content for map. Note that
     * this may be an ordinary Ruby hashmap or another Map instance with identical
     * key and value types. Also note that this argument may be present whether or
     * not value_typeclass is present (and it is unambiguously separate from
     * value_typeclass because value_typeclass's presence is strictly determined by
     * value_type). The contents of this initial hashmap or Map instance are
     * shallow-copied into the new Map: the original map is unmodified, but
     * references to underlying objects will be shared if the value type is a
     * message type.
     */

    @JRubyMethod(required = 2, optional = 2)
    public IRubyObject initialize(ThreadContext context, IRubyObject[] args) {
        this.table = new HashMap<IRubyObject, IRubyObject>();
        this.keyType = Utils.rubyToFieldType(args[0]);
        this.valueType = Utils.rubyToFieldType(args[1]);

        switch(keyType) {
            case INT32:
            case INT64:
            case UINT32:
            case UINT64:
            case BOOL:
            case STRING:
            case BYTES:
                // These are OK.
                break;
            default:
                throw context.runtime.newArgumentError("Invalid key type for map.");
        }

        int initValueArg = 2;
        if (needTypeclass(this.valueType) && args.length > 2) {
            this.valueTypeClass = args[2];
            Utils.validateTypeClass(context, this.valueType, this.valueTypeClass);
            initValueArg = 3;
        } else {
            this.valueTypeClass = context.runtime.getNilClass();
        }

        // Table value type is always UINT64: this ensures enough space to store the
        // native_slot value.
        if (args.length > initValueArg) {
            mergeIntoSelf(context, args[initValueArg]);
        }
        return this;
    }

    /*
     * call-seq:
     *     Map.[]=(key, value) => value
     *
     * Inserts or overwrites the value at the given key with the given new value.
     * Throws an exception if the key type is incorrect. Returns the new value that
     * was just inserted.
     */
    @JRubyMethod(name = "[]=")
    public IRubyObject indexSet(ThreadContext context, IRubyObject key, IRubyObject value) {
        Utils.checkType(context, keyType, key, (RubyModule) valueTypeClass);
        Utils.checkType(context, valueType, value, (RubyModule) valueTypeClass);
        IRubyObject symbol;
        if (valueType == Descriptors.FieldDescriptor.Type.ENUM &&
                Utils.isRubyNum(value) &&
                ! (symbol = RubyEnum.lookup(context, valueTypeClass, value)).isNil()) {
            value = symbol;
        }
        this.table.put(key, value);
        return value;
    }

    /*
     * call-seq:
     *     Map.[](key) => value
     *
     * Accesses the element at the given key. Throws an exception if the key type is
     * incorrect. Returns nil when the key is not present in the map.
     */
    @JRubyMethod(name = "[]")
    public IRubyObject index(ThreadContext context, IRubyObject key) {
        if (table.containsKey(key))
            return this.table.get(key);
        return context.runtime.getNil();
    }

    /*
     * call-seq:
     *     Map.==(other) => boolean
     *
     * Compares this map to another. Maps are equal if they have identical key sets,
     * and for each key, the values in both maps compare equal. Elements are
     * compared as per normal Ruby semantics, by calling their :== methods (or
     * performing a more efficient comparison for primitive types).
     *
     * Maps with dissimilar key types or value types/typeclasses are never equal,
     * even if value comparison (for example, between integers and floats) would
     * have otherwise indicated that every element has equal value.
     */
    @JRubyMethod(name = "==")
    public IRubyObject eq(ThreadContext context, IRubyObject _other) {
        if (_other instanceof RubyHash)
            return toHash(context).op_equal(context, _other);
        RubyMap other = (RubyMap) _other;
        if (this == other) return context.runtime.getTrue();
        if (!typeCompatible(other) || this.table.size() != other.table.size())
            return context.runtime.getFalse();
        for (IRubyObject key : table.keySet()) {
            if (! other.table.containsKey(key))
                return context.runtime.getFalse();
            if (! other.table.get(key).equals(table.get(key)))
                return context.runtime.getFalse();
        }
        return context.runtime.getTrue();
    }

    /*
     * call-seq:
     *     Map.inspect => string
     *
     * Returns a string representing this map's elements. It will be formatted as
     * "{key => value, key => value, ...}", with each key and value string
     * representation computed by its own #inspect method.
     */
    @JRubyMethod
    public IRubyObject inspect() {
        return toHash(getRuntime().getCurrentContext()).inspect();
    }

    /*
     * call-seq:
     *     Map.hash => hash_value
     *
     * Returns a hash value based on this map's contents.
     */
    @JRubyMethod
    public IRubyObject hash(ThreadContext context) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            for (IRubyObject key : table.keySet()) {
                digest.update((byte) key.hashCode());
                digest.update((byte) table.get(key).hashCode());
            }
            return context.runtime.newString(new ByteList(digest.digest()));
        } catch (NoSuchAlgorithmException ignore) {
            return context.runtime.newFixnum(System.identityHashCode(table));
        }
    }

    /*
     * call-seq:
     *     Map.keys => [list_of_keys]
     *
     * Returns the list of keys contained in the map, in unspecified order.
     */
    @JRubyMethod
    public IRubyObject keys(ThreadContext context) {
        return RubyArray.newArray(context.runtime, table.keySet());
    }

    /*
     * call-seq:
     *     Map.values => [list_of_values]
     *
     * Returns the list of values contained in the map, in unspecified order.
     */
    @JRubyMethod
    public IRubyObject values(ThreadContext context) {
        return RubyArray.newArray(context.runtime, table.values());
    }

    /*
     * call-seq:
     *     Map.clear
     *
     * Removes all entries from the map.
     */
    @JRubyMethod
    public IRubyObject clear(ThreadContext context) {
        table.clear();
        return context.runtime.getNil();
    }

    /*
     * call-seq:
     *     Map.each(&block)
     *
     * Invokes &block on each |key, value| pair in the map, in unspecified order.
     * Note that Map also includes Enumerable; map thus acts like a normal Ruby
     * sequence.
     */
    @JRubyMethod
    public IRubyObject each(ThreadContext context, Block block) {
        for (IRubyObject key : table.keySet()) {
            block.yieldSpecific(context, key, table.get(key));
        }
        return context.runtime.getNil();
    }

    /*
     * call-seq:
     *     Map.delete(key) => old_value
     *
     * Deletes the value at the given key, if any, returning either the old value or
     * nil if none was present. Throws an exception if the key is of the wrong type.
     */
    @JRubyMethod
    public IRubyObject delete(ThreadContext context, IRubyObject key) {
        return table.remove(key);
    }

    /*
     * call-seq:
     *     Map.has_key?(key) => bool
     *
     * Returns true if the given key is present in the map. Throws an exception if
     * the key has the wrong type.
     */
    @JRubyMethod(name = "has_key?")
    public IRubyObject hasKey(ThreadContext context, IRubyObject key) {
        return this.table.containsKey(key) ? context.runtime.getTrue() : context.runtime.getFalse();
    }

    /*
     * call-seq:
     *     Map.length
     *
     * Returns the number of entries (key-value pairs) in the map.
     */
    @JRubyMethod
    public IRubyObject length(ThreadContext context) {
        return context.runtime.newFixnum(this.table.size());
    }

    /*
     * call-seq:
     *     Map.dup => new_map
     *
     * Duplicates this map with a shallow copy. References to all non-primitive
     * element objects (e.g., submessages) are shared.
     */
    @JRubyMethod
    public IRubyObject dup(ThreadContext context) {
        RubyMap newMap = newThisType(context);
        for (Map.Entry<IRubyObject, IRubyObject> entry : table.entrySet()) {
            newMap.table.put(entry.getKey(), entry.getValue());
        }
        return newMap;
    }

    @JRubyMethod(name = {"to_h", "to_hash"})
    public RubyHash toHash(ThreadContext context) {
        return RubyHash.newHash(context.runtime, table, context.runtime.getNil());
    }

    // Used by Google::Protobuf.deep_copy but not exposed directly.
    protected IRubyObject deepCopy(ThreadContext context) {
        RubyMap newMap = newThisType(context);
        switch (valueType) {
            case MESSAGE:
                for (IRubyObject key : table.keySet()) {
                    RubyMessage message = (RubyMessage) table.get(key);
                    newMap.table.put(key.dup(), message.deepCopy(context));
                }
                break;
            default:
                for (IRubyObject key : table.keySet()) {
                    newMap.table.put(key.dup(), table.get(key).dup());
                }
        }
        return newMap;
    }

    protected List<DynamicMessage> build(ThreadContext context, RubyDescriptor descriptor) {
        List<DynamicMessage> list = new ArrayList<DynamicMessage>();
        RubyClass rubyClass = (RubyClass) descriptor.msgclass(context);
        Descriptors.FieldDescriptor keyField = descriptor.lookup("key").getFieldDef();
        Descriptors.FieldDescriptor valueField = descriptor.lookup("value").getFieldDef();
        for (IRubyObject key : table.keySet()) {
            RubyMessage mapMessage = (RubyMessage) rubyClass.newInstance(context, Block.NULL_BLOCK);
            mapMessage.setField(context, keyField, key);
            mapMessage.setField(context, valueField, table.get(key));
            list.add(mapMessage.build(context));
        }
        return list;
    }

    protected RubyMap mergeIntoSelf(final ThreadContext context, IRubyObject hashmap) {
        if (hashmap instanceof RubyHash) {
            ((RubyHash) hashmap).visitAll(new RubyHash.Visitor() {
                @Override
                public void visit(IRubyObject key, IRubyObject val) {
                    indexSet(context, key, val);
                }
            });
        } else if (hashmap instanceof RubyMap) {
            RubyMap other = (RubyMap) hashmap;
            if (!typeCompatible(other)) {
                throw context.runtime.newTypeError("Attempt to merge Map with mismatching types");
            }
        } else {
            throw context.runtime.newTypeError("Unknown type merging into Map");
        }
        return this;
    }

    protected boolean typeCompatible(RubyMap other) {
        return this.keyType == other.keyType &&
                this.valueType == other.valueType &&
                this.valueTypeClass == other.valueTypeClass;
    }

    private RubyMap newThisType(ThreadContext context) {
        RubyMap newMap;
        if (needTypeclass(valueType)) {
            newMap = (RubyMap) metaClass.newInstance(context,
                    Utils.fieldTypeToRuby(context, keyType),
                    Utils.fieldTypeToRuby(context, valueType),
                    valueTypeClass, Block.NULL_BLOCK);
        } else {
            newMap = (RubyMap) metaClass.newInstance(context,
                    Utils.fieldTypeToRuby(context, keyType),
                    Utils.fieldTypeToRuby(context, valueType),
                    Block.NULL_BLOCK);
        }
        newMap.table = new HashMap<IRubyObject, IRubyObject>();
        return newMap;
    }

    private boolean needTypeclass(Descriptors.FieldDescriptor.Type type) {
        switch(type) {
            case MESSAGE:
            case ENUM:
                return true;
            default:
                return false;
        }
    }

    private Descriptors.FieldDescriptor.Type keyType;
    private Descriptors.FieldDescriptor.Type valueType;
    private IRubyObject valueTypeClass;
    private Map<IRubyObject, IRubyObject> table;
}
