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

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

/**
 * ページインスタンスに対する入出力バイパスを持つ div タグ。
 * このタグに addHTMLPart してもブラウザへ出力されません。
 */
public class PageBypassedDiv extends Tag implements PageHooker {
	private static final long serialVersionUID = 2L;
	private Page	link_page;
	private Page	view_page;

	/**
	 * コンストラクタ。
	 */
	public PageBypassedDiv() {
		super( "div", false );
		makeID();
	}

	private static void setPageServerInformation( Page p, PageServerInformation psi ) {
		if ( p == null )	return;
		PageBypassedDiv[]	pbd = p.getPageBypassedDiv();
		for ( int i = 0; i < pbd.length; i++ ) {
			setPageServerInformation( pbd[i].getBypassPage(), psi );
		}
		p.setPageServerInformation( psi );
	}

	/**
	 * バイパス先の設定。
	 * @param history 履歴。
	 * @param page バイパスするページ。
	 */
	public void setBypassPage( History history, Page page ) {
		if ( link_page == page )	return;
		setModifyMyselef();
		setPageServerInformation( link_page, null );
		history.removeSatellitePage( link_page );
		view_page = page;
		link_page = page;
		if ( page != null ) {
			Page	ap = getAssignedPage();
			PageServerInformation	psi = ap.getPageServerInformation();
			setPageServerInformation( page, psi );
			page.setParentPage( ap );
			history.addSatellitePage( page );
		}
	}

	public Forward beforeInput( Page page, RequestParameter req, Forward fw ) throws Exception {
		return fw;
	}

	public void afterOutput( Page from, Page to, RequestParameter req ) throws Exception {
		commitDaemon();
	}

	public void commitDaemon() {
		if ( view_page == null )	return;
		getAssignedPage().addOnLoadScript( view_page.getOnLoadScript() );
		view_page.resetOnLoadScript();
	}

	/**
	 * バイパス先の取得。
	 * @return バイパスしているページ。
	 */
	public Page getBypassPage() {
		return link_page;
	}

	/**
	 * フレームワークが使用します。
	 */
	public Page getViewPage() {
		return view_page;
	}

	public void write( PrintWriter w, StringMode mode ) {
		if ( !isVisible() )	return;
		resetModify();
		w.print( getFirstTag() );
		if ( view_page != null ) {
			Tag	body = view_page.getBodyTag();
			if ( body != null ) {
				int	cnt = body.getHTMLPartCount();
				if ( mode != StringMode.TEXTAREA )	mode = StringMode.BODY;
				for ( int i = 0; i < cnt; i++ ) {
					body.getHTMLPart( i ).write( w, mode );
				}
			}
		}
		w.print( getLastTag() );
	}

	public boolean isModified() {
		if ( super.isModified() )	return true;
		if ( view_page == null )	return false;
		Tag	body = view_page.getBodyTag();
		if ( body == null )	return false;
		if ( !body.isModified() )	return false;
		body.resetModify();
		setModifyMyselef();
		return true;
	}

	protected void getModifiedTag( ArrayList<Tag> list ) {
		if ( view_page == null )	return;
		Tag	body = view_page.getBodyTag();
		if ( body != null ) {
			if ( isModified() ) {
				list.add( this );
				return;
			}
			Tag[]	tag = body.getModifiedTag();
			for ( int i = 0; i < tag.length; i++ ) {
				list.add( tag[i] );
			}
		}
	}

	/**
	 * フレームワークが使用します。
	 */
	public void setView( Page view ) {
		view_page = view;
		if ( view_page == null ) {
			view_page = link_page;
		}
		if ( view_page != link_page ) {
			//history.addSatellitePage( view_page );
System.out.println( "setView diff" );
		}
	}
}

