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

import java.io.*;
import java.util.*;
import paraselene.*;
import paraselene.ui.*;
import paraselene.tag.*;
import paraselene.ajax.data.*;

/**
 * バックグラウンドデーモンからのブラウザへの動作指示。
 */
public class DaemonForward {
	Page	page;
	Forward	forward;
	/**
	 * コンストラクタ。
	 * @param hint ブラウザを特定するために使用します。
	 * このページが表示されているブラウザに対し動作を指示します。
	 * このページへ Forward 指示を行うわけではありません。
	 * @param fw 動作内容。
	 */
	public DaemonForward( Page hint, Forward fw ) {
		page = hint;
		forward = fw;
		History	hist = hint.getPageServerInformation().getHistorySet().get( hint.getHistoryKey() );
		if ( forward instanceof Popup ) {
			Popup	pop = (Popup)forward;
			pop.initType( hist );
		}
		forward.initTrim( hist );
	}
}

class CometCall {
	History	hist;
	Page	next_page;
	Forward	forward;

	private void setModify( Page page ) {
		PageBypassedDiv[]	div = page.getPageBypassedDiv();
		for ( int i = 0; i < div.length; i++ ) {
			setModify( div[i].getBypassPage() );
		}
		PageHooker[]	hook = page.getPageHooker();
		for ( int i = 0; i < hook.length; i++ ) {
			Tag	tag = (Tag)hook[i];
			tag.setModify();
		}
	}

	CometCall( History h, Forward f ) {
		hist = h;
		next_page = f.getPage( null );
		if ( f.isRefresh( true ) ) {
			setModify( next_page );
		}
		forward = f;
	}

	PostBack[] make() throws Exception {
		return OutputCall.make( hist, next_page, new Page[]{ next_page, next_page }, false );
	}
}

class OpenCometCall extends CometCall {
	OpenCometCall( History h, Forward f, Popup.Type type ) {
		super( h, f );
		next_page.setPopupType( type );
	}

	PostBack[] make() throws Exception {
		return OpenOutput.make( (Popup)forward, hist, next_page, next_page, false );
	}
}

class CloseCometCall extends CometCall {
	CloseCometCall( History h, Closure f ) {
		super( h, f );
	}

	PostBack[] make() throws Exception {
		return CloseOutput.make( (Closure)forward, hist, next_page );
	}

}

class ScriptCometCall extends CometCall {
	ScriptCometCall( History h, Forward f ) {
		super( h, f );
	}

	PostBack[] make() throws Exception {
		return ScriptOutput.make( (JavaScript)forward );
	}
}

class NopCometCall extends CometCall {
	NopCometCall( History h, Forward f ) {
		super( h, f );
	}

	PostBack[] make() throws Exception {
		return NopOutput._make();
	}
}

class LocationCometCall extends CometCall {
	LocationCometCall( History h, Forward f ) {
		super( h, f );
	}

	PostBack[] make() throws Exception {
		String	url = null;
		if ( !forward.isLeave() ) {
			url = URIValue.pageToURI( forward.getPageID(), null );
		}
		else {
			url = forward.getRedirectURI().toString();
		}
		Page	dummy = hist.getPage();
		if ( dummy == null )	return new PostBack[0];
		Tag	tag = dummy.getMainTag();
		if ( tag == null )	return new PostBack[0];
		url = Supervisor.makeWithSessionURI( url, null, tag );
		Option.trace( "%s redirect JSON", url );
		return new PostBack[] { new PostBack( url ) };
	}
}

class CometHolder {
	private	Forward[]	forward = null;
	private CometCall[]	cc = null;

	CometHolder( History hist, Forward fw ) {
		AjaxForward[]	af = fw.getAjaxForward( true );
		if ( af != null ) {
			forward = new Forward[af.length];
			for ( int i = 0; i < af.length; i++ ) {
				forward[i] = (Forward)af[i];
			}
			cc = new CometCall[af.length];
		}
		else {
			forward = new Forward[] { fw };
			cc = new CometCall[1];
		}
		for ( int i = 0; i < forward.length; i++ ) {
			cc[i] = forward[i].makeCometCall( hist );
		}
	}

	Serializable[] getPostBack() throws Exception {
		ArrayList<Serializable>	ret = new ArrayList<Serializable>();
		for ( int i = 0; i < cc.length; i++ ) {
			PostBack[]	pb = cc[i].make();
			for ( int j = 0; j < pb.length; j++ ) {
				ret.add( pb[j] );
			}
		}
		return ret.toArray( new Serializable[0] );
	}
}

