/*******************************************************************************
 * Copyright (c) 2002, 2005 Object Factory Inc.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *		Object Factory Inc. - Initial implementation
 *******************************************************************************/
package org.eclipse.ant.internal.ui.dtd.util;

import com.ibm.icu.text.MessageFormat;
import java.util.Comparator;
import java.util.Iterator;

/**
 * @author Bob Foster
 */
public class SortedMap implements FactoryObject {

	private SortedSet fSet;
	private IMapHolder fHolder;
	private SortedMap fNext;
	
	public SortedMap(IMapHolder holder, Comparator comp) {
		fHolder = holder;
		fSet = new SortedSet(holder, comp);
	}
	
	public SortedMap(Comparator comp) {
		fSet = new SortedSet(comp);
	}
	
	public SortedMap(IMapHolder holder) {
		fHolder = holder;
		fSet = new SortedSet(holder);
	}
	
	public SortedMap() {
		fSet = new SortedSet();
	}
	
	public void setMapHolder(IMapHolder holder) {
		fHolder = holder;
		fSet.setKeyHolder(holder);
	}
	
	public void setComparator(Comparator comp) {
		fSet.setComparator(comp);
	}
	
	public boolean containsKey(Object key) {
		return fSet.contains(key);
	}
	
	public boolean containsKeyIdentity(Object key) {
		return fSet.containsIdentity(key);
	}
	
	public Object put(Object key, Object val) {
		Object[] values = fHolder.getValues();
		int index = fSet.indexOf(key);
		Object result = index >= 0 && values != null ? values[index] : null;
		
		int i = fSet.internalAdd(key, false);
		if (i >= 0)
			internalPut(i, val);
		return result;
	}
	
	protected void internalPut(int i, Object val) {
		Object[] values = fHolder.getValues();
		if (values == null) {
			values = new Object[1];
			values[0] = val;
			return;
		}
	
		Object[] tmp = new Object[values.length+1];
		System.arraycopy(values,0,tmp,0,i);
		tmp[i] = val;
		System.arraycopy(values,i,tmp,i+1,values.length-i);
		fHolder.setValues(tmp);
	}
	
	public int putAlways(Object key, Object val) {
		int i = fSet.internalAdd(key, true);
		internalPut(i, val);
		return i;
	}
	
	public void append(Object key, Object val) {
		Object[] values = fHolder.getValues();
		int len = values != null ? values.length : 0;
		fSet.internalAdd(len, key);
		internalPut(len, val);
	}
	
	public Object get(Object key) {
		Object[] values = fHolder.getValues();
		if (values == null)
			return null;
		int i = fSet.indexOf(key);
		if (i >= 0)
			return values[i];
		return null;
	}
	
	public Object getIdentity(Object key) {
		Object[] values = fHolder.getValues();
		if (values == null)
			return null;
		int i = fSet.indexOfIdentity(key);
		if (i >= 0)
			return values[i];
		return null;
	}
	
	public Object[] keys() {
		return fSet.members();
	}
	
	public Object[] values() {
		Object[] values = fHolder.getValues();
		if (values == null)
			return new Object[0];
		return values;
	}
	
	public Iterator keyIterator() {
		return new ArrayIterator();
	}

	public Iterator valueIterator() {
		return new ArrayIterator();
	}
	
	private class ArrayIterator implements Iterator {
		private int fIndex;
		
		public ArrayIterator() {
			fIndex = -1;
		}
		/**
		 * @see java.util.Iterator#hasNext()
		 */
		public boolean hasNext() {
			Object[] array = SortedMap.this.fHolder.getKeys();
			if (array == null)
				return false;
			return fIndex + 1 < array.length;
		}

		/**
		 * @see java.util.Iterator#next()
		 */
		public Object next() {
			Object[] array = SortedMap.this.fHolder.getKeys();
			if (array == null)
				throw new IllegalStateException(AntDTDUtilMessages.SortedMap_next___called_for_empty_array_1);
			return array[++fIndex];
		}

		/**
		 * @see java.util.Iterator#remove()
		 */
		public void remove() {
			SortedMap.this.remove(fIndex);
			--fIndex;
		}

	}
	
	public void remove(int i) {
		Object[] values = fHolder.getValues();
		if (values == null) {
			throw new IllegalArgumentException(MessageFormat.format(AntDTDUtilMessages.SortedMap_remove__0___in_empty_map_2, new String[]{Integer.toString(i)}));
		}
		fSet.remove(i);
		Object[] tmp = new Object[values.length-1];
		System.arraycopy(values,0,tmp,0,i);
		System.arraycopy(values,i+1,tmp,i,values.length-i-1);
		fHolder.setValues(tmp);
	}
	
	public Object remove(Object obj) {
		Object[] values = fHolder.getValues();
		if (values == null)
			return null;
		int i = fSet.indexOf(obj);
		if (i >= 0) {
			Object tmp = values[i];
			fSet.remove(i);
			remove(i);
			return tmp;
		}
		return null;
	}
	public Object removeIdentity(Object obj) {
		Object[] values = fHolder.getValues();
		if (values == null)
			return null;
		int i = fSet.indexOfIdentity(obj);
		if (i >= 0) {
			Object tmp = values[i];
			fSet.remove(i);
			remove(i);
			return tmp;
		}
		return null;
	}

	public int size() {
		return fSet.size();
	}
	
	public int keyIndex(Object key) {
		return fSet.indexOf(key);
	}
	
	public void merge(SortedMap other) {
		Object[] values = fHolder.getValues();
		Object[] keys = fHolder.getKeys();
		Object[] othervalues = other.fHolder.getValues();
		Object[] otherkeys = other.fHolder.getKeys();
		if (otherkeys == null)
			return;
		if (keys == null) {
			fHolder.setKeys(otherkeys);
			fHolder.setValues(othervalues);
			return;
		}
		int ithis = 0, iother = 0, i = 0;
		int mthis = keys.length, mother = otherkeys.length;
		Object[] ktmp = new Object[mthis+mother];
		Object[] vtmp = new Object[mthis+mother];
		while (ithis < mthis && iother < mother) {
			int comp = fSet.fComp.compare(keys[ithis], otherkeys[iother]);
			if (comp <= 0) {
				vtmp[i] = values[ithis];
				ktmp[i++] = keys[ithis++];
			}
			else {
				vtmp[i] = othervalues[iother];
				ktmp[i++] = otherkeys[iother++];
			}
		}
		while (ithis < mthis) {
			vtmp[i] = values[ithis];
			ktmp[i++] = keys[ithis++];
		}
		while (iother < mother) {
			vtmp[i] = othervalues[iother];
			ktmp[i++] = otherkeys[iother++];
		}
		fHolder.setKeys(ktmp);
		fHolder.setValues(vtmp);
	}
	
	public FactoryObject next() {
		return fNext;
	}
	
	public void next(FactoryObject next) {
		fNext = (SortedMap) next;
	}
}
