/*
 *
 *  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.apache.flex.utils;

import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;

/**
 * Implements a sparse mapping from int -> Object.  Iterators will
 * traverse from lowest to highest.  put() is O(1) if the key is
 * higher than any existing key; O(logN) if the key already exists,
 * and O(N) otherwise.  get() is an O(logN) binary search.
 */
public class IntMap
{
    private int[] keys;
    private Object[] values;
    private int size;

    public IntMap()
    {
        this(10);
    }

    public IntMap(int capacity)
    {
        keys = new int[capacity];
        values = new Object[capacity];
    }

	public int capacity()
	{
		return keys.length;
	}

    private int find(int k)
    {
        int lo = 0;
        int hi = size-1;

        while (lo <= hi)
        {
            int i = (lo + hi) >>> 1;
            int m = keys[i];
            if (k > m)
                lo = i + 1;
            else if (k < m)
                hi = i - 1;
            else
                return i; // key found
        }
        return -(lo + 1);  // key not found, low is the insertion point
    }

    public Object remove(int k)
    {
        Object old = null;
        int i = find(k);
        if (i >= 0)
        {
            old = values[i];
            System.arraycopy(keys, i+1, keys, i, size-i-1);
            System.arraycopy(values, i+1, values, i, size-i-1);
            size--;
        }
        return old;
    }

	public void clear()
	{
		size = 0;
	}

    public Object put(int k, Object v)
    {
        if (size == 0 || k > keys[size-1])
        {
            if (size == keys.length)
                grow();
            keys[size] = k;
            values[size] = v;
            size++;
            return null;
        }
        else
        {
            int i = find(k);
            if (i >= 0)
            {
                Object old = values[i];
                values[i] = v;
                return old;
            }
            else
            {
                i = -i - 1; // recover the insertion point
                if (size == keys.length)
                    grow();
                System.arraycopy(keys,i,keys,i+1,size-i);
                System.arraycopy(values,i,values,i+1,size-i);
                keys[i] = k;
                values[i] = v;
                size++;
                return null;
            }
        }
    }

    private void grow()
    {
        int[] newkeys = new int[size*2];
        System.arraycopy(keys,0,newkeys,0,size);
        keys = newkeys;

        Object[] newvalues = new Object[size*2];
        System.arraycopy(values,0,newvalues,0,size);
        values = newvalues;
    }

    public Object get(int k)
    {
        int i = find(k);
        return i >= 0 ? values[i] : null;
    }

    public boolean contains(int k)
    {
        return find(k) >= 0;
    }

	/** 
	 * A bit of an aberration from an academic point of view,
	 * but since this is an ordered Map, why not!
	 * 
	 * @return the element immediately following element k.
	 */
	public Object getNextAdjacent(int k)
	{
		int i = find(k);
		return ( (i >= 0) && (i+1 < size) ) ? values[i+1] : null;
	}

    public Iterator<Map.Entry<Integer, Object>> iterator()
    {
        return new Iterator<Map.Entry<Integer, Object>>()
        {
            private int i = 0;
            @Override
            public boolean hasNext()
            {
                return i < size;
            }

            @Override
            public Map.Entry<Integer, Object> next()
            {
                if (i >= size)
                {
                    throw new NoSuchElementException();
                }
                final int j = i++;
                return new Map.Entry<Integer, Object>()
                {
                    @Override
                    public Integer getKey()
                    {
                        return keys[j];
                    }

                    @Override
                    public Object getValue()
                    {
                        return values[j];
                    }

                    @Override
                    public Object setValue(Object value)
                    {
                        Object old = values[j];
                        values[j] = value;
                        return old;
                    }
                };
            }

            @Override
            public void remove()
            {
                System.arraycopy(keys, i, keys, i-1, size-i);
                System.arraycopy(values, i, values, i-1, size-i);
                size--;
            }
        };
    }

    public int size()
    {
        return size;
    }

	/** 
	 * @param ar must be of size size().
	 */
	public Object[] valuesToArray(Object[] ar)
	{
		System.arraycopy(values, 0, ar, 0, size);
		return ar;
	}

	public int[] keySetToArray()
	{
		int[] ar = new int[size()];
		System.arraycopy(keys, 0, ar, 0, size);
		return ar;
	}
}
