/*
 * Written by Dawid Kurzyniec and released to the public domain, as explained
 * at http://creativecommons.org/licenses/publicdomain
 */

package edu.emory.mathcs.util.collections.shorts;

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

/**
 * @author Dawid Kurzyniec
 * @version 1.0
 */
public class ShortCollections {
    private ShortCollections() {}

    public static ShortInterval interval(short first, short last) {
        return (first > last) ? EMPTY_INTERVAL : new SimpleInterval(first, last);
    }

    public static final ShortInterval EMPTY_INTERVAL = new AbstractShortInterval() {
        public boolean isEmpty() { return true; }
        public short getFirst() { return 0; }
        public short getLast() { return -1; }
        public short min() { return 0; }
        public short max() { return -1; }
    };

    public static final ShortList EMPTY_LIST = new ShortArrAsList(new short[0]);

    public static class SimpleInterval extends AbstractShortInterval {
        final short first, last;
        public SimpleInterval(short first, short last) {
            if (first > last) throw new IllegalArgumentException();
            this.first = first;
            this.last = last;
        }
        public short getFirst() { return first; }
        public short getLast() { return last; }

        public short first() { return first; }
        public short last() { return last; }

        public short min() { return first; }
        public short max() { return last; }
    }

    public static ShortList asList(short[] arr) {
        return new ShortArrAsList(arr);
    }

    private static class ShortArrAsList extends AbstractShortCollection
                                       implements ShortList {
        final short[] arr;
        ShortArrAsList(short[] arr) {
            this.arr = arr;
        }

        public int size() { return arr.length; }

        public boolean isEmpty() { return arr.length == 0; }

        public boolean contains(short e) {
            for (int i=0; i<arr.length; i++) {
                if (arr[i] == e) return true;
            }
            return false;
        }

        public ShortIterator iterator() {
            return listIterator();
        }

        public short[] toArray() {
            short[] a = new short[arr.length];
            System.arraycopy(arr, 0, a, 0, arr.length);
            return a;
        }

        public short[] toArray(short[] a) {
            if (a.length < arr.length) {
                a = new short[arr.length];
            }
            System.arraycopy(arr, 0, a, 0, arr.length);
            return a;
        }

        public boolean add(short e) {
            throw new UnsupportedOperationException();
        }

        public boolean addAll(int idx, ShortCollection c) {
            throw new UnsupportedOperationException();
        }

        public boolean remove(short e) {
            throw new UnsupportedOperationException();
        }

        public void clear() {
            throw new UnsupportedOperationException();
        }

        public boolean equals(Object o) {
            if (o == this) return true;
            if (!(o instanceof ShortList)) return false;
            ShortList that = (ShortList)o;
            if (this.size() != that.size()) return false;
            for (int i=0; i<arr.length; i++) {
                if (arr[i] != that.getAt(i)) return false;
            }
            return true;
        }

        public int hashCode() {
            int hashCode = 1;
            for (int i=0; i<arr.length; i++) {
                hashCode = 31*hashCode + (int)arr[i];
            }
            return hashCode;
        }

        public short getAt(int index) { return arr[index]; }

        public short setAt(int index, short e) {
            short old = arr[index];
            arr[index] = e;
            return old;
        }

        public void addAt(int index, short e) {
            throw new UnsupportedOperationException();
        }

        public short removeAt(int index) {
            throw new UnsupportedOperationException();
        }

        public int indexOf(short e) {
            for (int i=0; i<arr.length; i++) {
                if (arr[i] == e) return i;
            }
            return -1;
        }

        public int lastIndexOf(short e) {
            for (int i=arr.length-1; i>=0; --i) {
                if (arr[i] == e) return i;
            }
            return -1;
        }

        public ShortListIterator listIterator() {
            return new ArrAsListItr(0);
        }

        public ShortListIterator listIterator(int index) {
            return new ArrAsListItr(index);
        }

        public ShortList subList(int fromIndex, int toIndex) {
            throw new UnsupportedOperationException();
        }

        private class ArrAsListItr implements ShortListIterator {
            int cursor;
            ArrAsListItr(int cursor) {
                this.cursor = cursor;
            }
            public boolean hasNext() { return cursor < arr.length; }

            public short next() {
                if (cursor == arr.length) {
                    throw new NoSuchElementException();
                }
                return arr[cursor++];
            }

            public boolean hasPrevious() { return cursor > 0; }

            public short previous() {
                if (cursor == 0) {
                    throw new NoSuchElementException();
                }
                return arr[--cursor];
            }

            public int nextIndex() { return cursor; }

            public int previousIndex() { return cursor-1; }

            public void remove() { throw new UnsupportedOperationException(); }

            public void set(short e) { arr[cursor] = e; }

            public void add(short e) { throw new UnsupportedOperationException(); }
        }
    }

}
