/*
 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package jdk.nashorn.internal.codegen;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import jdk.nashorn.internal.runtime.PropertyMap;

/**
 * Manages constants needed by code generation.  Objects are maintained in an
 * interning maps to remove duplicates.
 */
final class ConstantData {
    /** Constant table. */
    final List<Object> constants;

    /** Constant table string interning map. */
    final Map<String, Integer> stringMap;

    /** Constant table object interning map. */
    final Map<Object, Integer> objectMap;

    private static class ArrayWrapper {
        private final Object array;
        private final int    hashCode;

        public ArrayWrapper(final Object array) {
            this.array    = array;
            this.hashCode = calcHashCode();
        }

        /**
         * Calculate a shallow hashcode for the array.
         * @return Hashcode with elements factored in.
         */
        private int calcHashCode() {
            final Class<?> cls = array.getClass();

            if (!cls.getComponentType().isPrimitive()) {
                return Arrays.hashCode((Object[])array);
            } else if (cls == double[].class) {
                return Arrays.hashCode((double[])array);
            } if (cls == long[].class) {
                return Arrays.hashCode((long[])array);
            } if (cls == int[].class) {
                return Arrays.hashCode((int[])array);
            }

            throw new AssertionError("ConstantData doesn't support " + cls);
        }

        @Override
        public boolean equals(final Object other) {
            if (!(other instanceof ArrayWrapper)) {
                return false;
            }

            final Object otherArray = ((ArrayWrapper)other).array;

            if (array == otherArray) {
                return true;
            }

            final Class<?> cls = array.getClass();

            if (cls == otherArray.getClass()) {
                if (!cls.getComponentType().isPrimitive()) {
                    return Arrays.equals((Object[])array, (Object[])otherArray);
                } else if (cls == double[].class) {
                    return Arrays.equals((double[])array, (double[])otherArray);
                } else if (cls == long[].class) {
                    return Arrays.equals((long[])array, (long[])otherArray);
                } else if (cls == int[].class) {
                    return Arrays.equals((int[])array, (int[])otherArray);
                }
            }

            return false;
        }

        @Override
        public int hashCode() {
            return hashCode;
        }
    }

    /**
     * {@link PropertyMap} wrapper class that provides implementations for the {@code hashCode} and {@code equals}
     * methods that are based on the map layout. {@code PropertyMap} itself inherits the identity based implementations
     * from {@code java.lang.Object}.
     */
    private static class PropertyMapWrapper {
        private final PropertyMap propertyMap;
        private final int hashCode;

        public PropertyMapWrapper(final PropertyMap map) {
            this.hashCode = Arrays.hashCode(map.getProperties()) + 31 * Objects.hashCode(map.getClassName());
            this.propertyMap = map;
        }

        @Override
        public int hashCode() {
            return hashCode;
        }

        @Override
        public boolean equals(final Object other) {
            if (!(other instanceof PropertyMapWrapper)) {
                return false;
            }
            final PropertyMap otherMap = ((PropertyMapWrapper) other).propertyMap;
            return propertyMap == otherMap
                    || (Arrays.equals(propertyMap.getProperties(), otherMap.getProperties())
                        && Objects.equals(propertyMap.getClassName(), otherMap.getClassName()));
        }
    }

    /**
     * Constructor
     */
    ConstantData() {
        this.constants = new ArrayList<>();
        this.stringMap = new HashMap<>();
        this.objectMap = new HashMap<>();
    }

    /**
     * Add a string to the constant data
     *
     * @param string the string to add
     * @return the index in the constant pool that the string was given
     */
    public int add(final String string) {
        final Integer value = stringMap.get(string);

        if (value != null) {
            return value.intValue();
        }

        constants.add(string);
        final int index = constants.size() - 1;
        stringMap.put(string, index);

        return index;
    }

    /**
     * Add an object to the constant data
     *
     * @param object the string to add
     * @return the index in the constant pool that the object was given
     */
    public int add(final Object object) {
        assert object != null;
        final Object  entry;
        if (object.getClass().isArray()) {
            entry = new ArrayWrapper(object);
        } else if (object instanceof PropertyMap) {
            entry = new PropertyMapWrapper((PropertyMap) object);
        } else {
            entry = object;
        }
        final Integer value = objectMap.get(entry);

        if (value != null) {
            return value.intValue();
        }

        constants.add(object);
        final int index = constants.size() - 1;
        objectMap.put(entry, index);

        return index;
    }

    Object[] toArray() {
        return constants.toArray();
    }
}
