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

import paraselene.*;

/**
 * 遷移先指定。output するページをポップアップ表示します。<br>
 * ただし、遷移元ページのgetAjaxSupportが有効でない場合は、通常の Forward と等価です。
 */
public class Popup extends Forward implements AjaxForward {
	private static final long serialVersionUID = 2L;
	Page active_page = null;
	Page view_page = null;
	/**
	 * ポップアップ種別。
	 */
	public enum Type {
		/**
		 * ポップアップの下のページのUI操作を許す。
		 */
		MODELESS( false, true ),
		/**
		 * ポップアップの下のページのUI操作を禁止する。
		 */
		MODAL( true, true ),
		/**
		 * タイトルバーの無いモーダルダイアログ。
		 */
		LITE_MODAL( true, false );
		private boolean modal_f;
		private boolean move_f;
		private Type( boolean md_f, boolean mv_f ) {
			modal_f = md_f;
			move_f = mv_f;
		}
		/**
		 * タイトルバーの有無。
		 * @return true:存在する、false:存在しない。
		 */
		public boolean isTitle() {
			return move_f;
		}
		/**
		 * モーダルであるか？
		 * @return true:モーダル、false:モードレス。
		 */
		public boolean isMode() {
			return modal_f;
		}
		/**
		 * モーダルであるか？
		 * @return true:モーダル、false:モードレスまたはダイアログではない。
		 */
		public static boolean isMode( Page page ) {
			Type	ptype = page.getPopupType();
			if ( ptype == null )	return false;
			return ptype.isMode();
		}
	}

	private Type type;

	boolean is_refresh() {
		return view_page != null;
	}

	/**
	 * コンストラクタ。新しいダイアログを表示します。
	 * @param id 表示するページ。
	 * @param dialog_type ポップアップ種別。
	 */
	public Popup( PageID id, Type dialog_type ) {
		super( id );
		type = dialog_type;
		if ( SandBox.isCurrentDaemon() )	return;
		initType( SandBox.getCurrentRequestParameter().getHistory() );
	}

	void initType( History hist ) {
		if ( isModelessAlert( type, hist, false ) ) {
			overwriteType( Type.MODAL );
		}
	}

	/**
	 * コンストラクタ。新しいダイアログを表示します。
	 * または、指定ページの Z順を手前にします。<br>
	 * 指定pageがダイアログであればアクティブ指示となり、そうでなければ
	 * 新規ダイアログとしてポップアップ表示します。
	 * @param page 表示するページ。
	 * @param dialog_type ポップアップ種別。
	 */
	public Popup( Page page, Type dialog_type ) {
		this( page.getParentPage().getID(), dialog_type );
		page = page.getParentPage();
		if ( page.getPopupType() != null ) {
			active_page = page;
		}
		else {
			view_page = page;
		}
	}

	static boolean isModeless( Type mine ) {
		if ( mine == null )	return false;
		return !mine.isMode();
	}

	static boolean isModelessAlert( Type mine, History hist, boolean unlock_f ) {
		if ( hist == null )	return false;
		if ( mine == null )	return false;
		if ( mine.isMode() )	return false;
		try {
			Page[]	page = hist.getBrowsingPage();
			for ( int i = 0; i < page.length; i++ ) {
				Type	ptype = page[i].getPopupType();
				if ( ptype == null )	continue;
				if ( ptype.isMode() )	return true;
			}
		}
		finally {
			if ( unlock_f )	hist.unlock();
		}
		return false;
	}

	/**
	 * コンストラクタ。<br>
	 * new Popup( page, Popup.Type.MODELESS ) と等価です。
	 * @param page MODELESSのポップアップ。
	 */
	public Popup( Page page ) {
		this( page, Type.MODELESS );
	}

	Page getPage( Page from ) {
		if ( active_page != null ) {
			Option.trace( "Popup#getPage -> %s", active_page.getUniqueKey() );
			return active_page;
		}
		if ( out_page == null ) {
			Option.trace( "Popup#getPage -> null" );
			return null;
		}
		if ( view_page != null ) {
			Option.trace( "Popup#getPage -> %s", view_page.getUniqueKey() );
			return view_page;
		}
		Page	p = out_page.getPageFactory().getPage( out_page.getID() );
		Option.trace( "Popup#getPage -> %s", p.getUniqueKey() );
		return p;
	}

	void overwriteType( Type t ) {
		if ( type == null )	return;
		if ( t == Type.MODELESS )	return;
		type = t;
	}

	Type getType() {
		return type;
	}

	/**
	 * 同じ動作であるか？
	 * 常にfalseを返します。
	 * @param o 比較対象。
	 * @return true:同一動作、false:異なる動作。
	 */
	public boolean equals( Object o ) {
		return false;
	}

	public String toString() {
		StringBuilder	buf = new StringBuilder( "Popup " );
		if ( active_page != null ) {
			buf = buf.append( "active:" );
			buf = buf.append( active_page.getID().toString() );
			buf = buf.append( "/" ).append( active_page.getUniqueKey() );
		}
		else {
			buf = buf.append( "open:" );
			if ( view_page == null ) {
				buf = buf.append( getPageID().toString() );
			}
			else {
				buf = buf.append( view_page.getID().toString() );
				buf = buf.append( "/" ).append( view_page.getUniqueKey() );
			}
			buf = buf.append( "/" ).append( type.toString() );
		}
		return buf.toString();
	}

	OutputCall makeOutput( int nk, Page lp, RequestParameter r, SessionData sd ) {
		Option.trace( "new OpenOutput <- %s", this );
		return new OpenOutput( nk, lp, this, getType(), r, sd );
	}

	CometCall makeCometCall( History h ) {
		Option.trace( "new OpenCometCall <- %s", this );
		return new OpenCometCall( h, this, getType() );
	}
}

