package online.view.el;

import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.NoSuchElementException;

import online.view.model.ViewMap;
import core.config.Factory;

/**
 * バンドリスト
 *
 * @author Tadashi Nakayama
 */
final class BandList implements List<Serializable>, Serializable {

	/** serialVersionUID */
	private static final long serialVersionUID = 1L;

	/** ViewMap */
	private final ViewMap vm;
	/** サイズ */
	private final int size;

	/**
	 * コンストラクタ
	 *
	 * @param map ViewMap
	 * @param item 基準項目名
	 */
	BandList(final ViewMap map, final String item) {
		this.vm = map;
		final Map<String, Serializable> m = Factory.cast(map.get(ViewMap.ATTR_ARRAY));
		final List<Serializable> list = Factory.cast(m.get(item));
		if (list != null) {
			this.size = list.size();
		} else {
			this.size = 0;
		}
	}

	/**
	 * ViewMap取得
	 *
	 * @return ViewMap
	 */
	ViewMap getViewMap() {
		return this.vm;
	}

	/**
	 * @see java.util.List#size()
	 */
	@Override
	public int size() {
		return this.size;
	}

	/**
	 * @see java.util.List#isEmpty()
	 */
	@Override
	public boolean isEmpty() {
		return this.size == 0;
	}

	/**
	 * @see java.util.List#contains(java.lang.Object)
	 */
	@Override
	public boolean contains(final Object o) {
		throw new UnsupportedOperationException();
	}

	/**
	 * @see java.util.List#iterator()
	 */
	@Override
	public Iterator<Serializable> iterator() {
		return new BandListIterator(this, getViewMap(), 0);
	}

	/**
	 * @see java.util.List#toArray()
	 */
	@Override
	public Object[] toArray() {
		throw new UnsupportedOperationException();
	}

	/**
	 * @see java.util.List#toArray(T[])
	 */
	@Override
	public <T> T[] toArray(final T[] a) {
		throw new UnsupportedOperationException();
	}

	/**
	 * @see java.util.List#add(java.lang.Object)
	 */
	@Override
	public boolean add(final Serializable e) {
		throw new UnsupportedOperationException();
	}

	/**
	 * @see java.util.List#remove(java.lang.Object)
	 */
	@Override
	public boolean remove(final Object o) {
		throw new UnsupportedOperationException();
	}

	/**
	 * @see java.util.List#containsAll(java.util.Collection)
	 */
	@Override
	public boolean containsAll(final Collection<?> c) {
		throw new UnsupportedOperationException();
	}

	/**
	 * @see java.util.List#addAll(java.util.Collection)
	 */
	@Override
	public boolean addAll(final Collection<? extends Serializable> c) {
		throw new UnsupportedOperationException();
	}

	/**
	 * @see java.util.List#addAll(int, java.util.Collection)
	 */
	@Override
	public boolean addAll(final int index, final Collection<? extends Serializable> c) {
		throw new UnsupportedOperationException();
	}

	/**
	 * @see java.util.List#removeAll(java.util.Collection)
	 */
	@Override
	public boolean removeAll(final Collection<?> c) {
		throw new UnsupportedOperationException();
	}

	/**
	 * @see java.util.List#retainAll(java.util.Collection)
	 */
	@Override
	public boolean retainAll(final Collection<?> c) {
		throw new UnsupportedOperationException();
	}

	/**
	 * @see java.util.List#clear()
	 */
	@Override
	public void clear() {
		throw new UnsupportedOperationException();
	}

	/**
	 * @see java.util.List#get(int)
	 */
	@Override
	public Serializable get(final int index) {
		return new BandMap(this.vm, index);
	}

	/**
	 * @see java.util.List#set(int, java.lang.Object)
	 */
	@Override
	public Serializable set(final int index, final Serializable element) {
		throw new UnsupportedOperationException();
	}

	/**
	 * @see java.util.List#add(int, java.lang.Object)
	 */
	@Override
	public void add(final int index, final Serializable element) {
		throw new UnsupportedOperationException();
	}

	/**
	 * @see java.util.List#remove(int)
	 */
	@Override
	public Serializable remove(final int index) {
		throw new UnsupportedOperationException();
	}

	/**
	 * @see java.util.List#indexOf(java.lang.Object)
	 */
	@Override
	public int indexOf(final Object o) {
		throw new UnsupportedOperationException();
	}

	/**
	 * @see java.util.List#lastIndexOf(java.lang.Object)
	 */
	@Override
	public int lastIndexOf(final Object o) {
		throw new UnsupportedOperationException();
	}

	/**
	 * @see java.util.List#listIterator()
	 */
	@Override
	public ListIterator<Serializable> listIterator() {
		return new BandListIterator(this, getViewMap(), 0);
	}

	/**
	 * @see java.util.List#listIterator(int)
	 */
	@Override
	public ListIterator<Serializable> listIterator(final int index) {
		return new BandListIterator(this, getViewMap(), index);
	}

	/**
	 * @see java.util.List#subList(int, int)
	 */
	@Override
	public List<Serializable> subList(final int fromIndex, final int toIndex) {
		throw new UnsupportedOperationException();
	}

	/**
	 * 内部イテレータ
	 *
	 * @author Tadashi Nakayama
	 */
	private static final class BandListIterator implements ListIterator<Serializable> {
		/** 現在位置 */
		private int loc;
		/** List */
		private final List<Serializable> list;
		/** BandMap */
		private final BandMap bm;

		/**
		 * コンストラクタ
		 *
		 * @param val インスタンス
		 * @param map ViewMap
		 * @param begin 開始位置
		 */
		BandListIterator(final List<Serializable> val, final ViewMap map, final int begin) {
			this.list = val;
			this.bm = new BandMap(map);
			this.loc = begin;
		}

		/**
		 * @see java.util.ListIterator#hasNext()
		 */
		@Override
		public boolean hasNext() {
			return 0 <= this.loc && this.loc < this.list.size();
		}

		/**
		 * @see java.util.ListIterator#next()
		 */
		@Override
		public Serializable next() {
			if (this.list.size() <= this.loc) {
				throw new NoSuchElementException();
			}

			this.bm.setIndex(this.loc++);
			return this.bm;
		}

		/**
		 * @see java.util.ListIterator#remove()
		 */
		@Override
		public void remove() {
			throw new UnsupportedOperationException();
		}

		/**
		 * @see java.util.ListIterator#hasPrevious()
		 */
		@Override
		public boolean hasPrevious() {
			return 0 < this.loc;
		}

		/**
		 * @see java.util.ListIterator#previous()
		 */
		@Override
		public Serializable previous() {
			if (this.loc <= 0) {
				throw new NoSuchElementException();
			}
			this.bm.setIndex(this.loc--);
			return this.bm;
		}

		/**
		 * @see java.util.ListIterator#nextIndex()
		 */
		@Override
		public int nextIndex() {
			return this.loc;
		}

		/**
		 * @see java.util.ListIterator#previousIndex()
		 */
		@Override
		public int previousIndex() {
			return this.loc - 1;
		}

		/**
		 * @see java.util.ListIterator#set(java.lang.Object)
		 */
		@Override
		public void set(final Serializable e) {
			throw new UnsupportedOperationException();
		}

		/**
		 * @see java.util.ListIterator#add(java.lang.Object)
		 */
		@Override
		public void add(final Serializable e) {
			throw new UnsupportedOperationException();
		}
	}
}
