/*
 * Paraselene
 * Copyright (c) 2009  Akira Terasaki
 * このファイルは同梱されているLicense.txtに定めた条件に同意できる場合にのみ
 * 利用可能です。
 */
package paraselene.supervisor;


import java.util.*;
import java.io.*;
import paraselene.*;

/**
 * 画面遷移履歴。<br>
 * スレッドセーフです。
 */
public class History implements Serializable {
	private static final long serialVersionUID = 2L;
	private ArrayList<Page>	hist = new ArrayList<Page>();
	private int	histry_no;

	/**
	 * コンストラクタ。
	 */
	private History() {}
	History( int n ) {
		histry_no = n;
	}

	/**
	 * 追加。
	 * @param page 追加するページ。
	 */
	public void add( Page page ) {
		if ( page == null )	return;
		synchronized( hist ) {
			if ( page.isHistoryClear() ) {
				int	cnt = getHistoryCount();
				for ( int i = 0; i < cnt; i++ ) {
					Page	h = hist.get( i );
					if ( page.equals( h ) ) {
						for ( int j = cnt -1; j >= i; j-- ) {
							hist.remove( j ).setHistoryKey( HistorySet.ROOT );
						}
						break;
					}
				}
			}
			if ( page.isAllowHistoryAdd() ) {
				hist.add( page );
				page.setHistoryKey( histry_no );
			}
		}
	}

	/**
	 * 履歴の件数を取得。
	 * @return 履歴件数。
	 */
	public int getHistoryCount() {
		return hist.size();
	}

	/**
	 * 履歴を取得。指定ページと同じものを履歴から取得します。
	 * @param id 指定ページ。
	 * @return 指定ページと同じページ。無ければnullを返す。
	 */
	public Page getPage( PageID id ) {
		if ( id == null ) return null;
		synchronized( hist ) {
			int	cnt = getHistoryCount();
			for ( int i = 0; i < cnt; i++ ) {
				Page	h = hist.get( i );
				if ( h.equals( id ) ) {
					return h;
				}
			}
		}
		return null;
	}

	/**
	 * 履歴を削除。
	 * @param last_no
	 * 0:直前のページ ～ getHistoryCount()-1:最古のページ。
	 */
	public void removePage( int last_no ) {
		if ( last_no < 0 )	return;
		synchronized( hist ) {
			int	cnt = getHistoryCount();
			for ( int i = cnt - 1; i >= 0; i-- ) {
				if ( last_no == 0 )	{
					hist.remove( i ).setHistoryKey( HistorySet.ROOT );
					return;
				}
				last_no--;
			}
		}
	}

	/**
	 * 履歴を削除。指定ページIDなら、全て削除する。
	 * @param page_id ページID。
	 */
	public void removePage( PageID page_id ) {
		synchronized( hist ) {
			int	cnt = getHistoryCount();
			for ( int i = cnt - 1; i >= 0; i-- ) {
				Page	page = hist.get( i );
				if ( page.getID() == page_id )	{
					hist.remove( i ).setHistoryKey( HistorySet.ROOT );
				}
			}
		}
	}

	/**
	 * 履歴を全て削除。
	 */
	public void removePage() {
		synchronized( hist ) {
			int	cnt = getHistoryCount();
			for ( int i = 0; i < cnt; i++ ) {
				hist.get( i ).setHistoryKey( HistorySet.ROOT );
			}
			hist.clear();
		}
	}

	/**
	 * 履歴を取得。
	 * @param last_no
	 * 0:直前のページ ～ getHistoryCount()-1:最古のページ。<br>
	 * 範囲外であるとnullを返す。
	 * @return 指定ページの内容。
	 */
	public Page getPage( int last_no ) {
		if ( last_no < 0 )	return null;
		synchronized( hist ) {
			int	cnt = getHistoryCount();
			for ( int i = cnt - 1; i >= 0; i-- ) {
				if ( last_no == 0 )	{
					return hist.get( i );
				}
				last_no--;
			}
		}
		return null;
	}

	/**
	 * 直前のページを取得。getPage(0)と等価。
	 * @return 遷移元ページ。
	 */
	public Page getPage() {
		return getPage( 0 );
	}
}

