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

import paraselene.*;
import paraselene.ui.*;
import paraselene.tag.form.*;
import paraselene.supervisor.*;
import java.io.*;
import java.net.*;
import java.util.*;

/**
 * Aタグ。
 */
public class Anchor extends Tag implements PageHooker, Clickable {
	private static final long serialVersionUID = 2L;
	private static final String	ANCHOR_ID = "paraselene$anchor$id";
	private static final String	ANCHOR_URL_ID = "paraselene$anchor$dummy";

	private boolean fix_id_f = false;
	private static volatile byte seq = 0;

	private String make_id() {
		long d = 0;
		synchronized( ANCHOR_ID ) {
			seq++;
			d = seq;
		}
		d <<= 56;
		d |= (new Date().getTime() & 0x00ffffffffffffffL);
		return Long.toString( d, Character.MAX_RADIX );
	}

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

	/**
	 * URL固定指定。デフォルト false です。
	 * @param flag true:固定にする、false:毎回変更する。
	 */
	public void setFixedURL( boolean flag ) {
		fix_id_f = flag;
	}

	/**
	 * URL固定状態の取得。デフォルト false です。
	 * @return true:固定にする、false:毎回変更する。
	 */
	public boolean isFixedURL() {
		return fix_id_f;
	}

	protected Tag newReplica() {
		Anchor	a = new Anchor();
		a.setUserData( getUserData() );
		return a;
	}

	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();

		Attribute	href = getAttribute( "href" );
		if ( href == null )	return;
		String	url = href.getString();
		if ( req.getSupervisor().isMyHostURI( url ) && url.charAt( 0 ) != '/' ) {
			URIValue	uv = (URIValue)href.get();
			QueryItem[]	item = uv.getQuery();
			ArrayList<QueryItem>	list = new ArrayList<QueryItem>();
			for ( int i = 0; i < item.length; i++ ) {
				if ( Form.PAGE_UKEY.equals( item[i].getName() ) ||
					ANCHOR_ID.equals( item[i].getName() ) ||
					ANCHOR_URL_ID.equals( item[i].getName() )
				) {
					if ( isClicked() )	continue;
					return;
				}
				list.add( item[i] );
			}
			if ( !fix_id_f ) {
				list.add( new QueryItem( ANCHOR_URL_ID, make_id() ) );
			}
			Page	my_page = getAssignedPage();
			if ( my_page.isAjax() && !req.getSupervisor().getPageFactory().isAlias( url ) ) {
				list.add( new QueryItem( Form.PAGE_UKEY, my_page.getUniqueKey() ) );
			}
			list.add( new QueryItem( ANCHOR_ID, makeID() ) );
			uv.setQuery( list.toArray( new QueryItem[0] ) );
		}
	}

	public void commitDaemon() {
		if ( !isAjaxEnable() )	return;
		StringBuilder	buf = new StringBuilder( "function(ev){" );
		buf = buf.append( "if(!paraselene.agency_a(paraselene.get_id('" );
		buf = buf.append( makeID() );
		buf = buf.append( "'),'" );
		buf = buf.append( getAssignedPage().getUniqueKey() );
		buf = buf.append( "'))paraselene.kill_event(ev);}" );
		setAnonymousEventHandler( "click", buf.toString() );
	}

	private boolean	pushed = false;
	private Object	obj = null;

	public boolean isClicked() {
		return pushed;
	}

	public void setClicked( boolean flag ) {
		pushed = flag;
	}

	public Object getUserData() {
		return obj;
	}

	public void setUserData( Object user_date ) {
		obj = user_date;
	}

	public boolean isClicked( RequestParameter req ) {
		RequestItem	item = req.getItem( ANCHOR_ID );
		if ( item == null )	return false;
		return makeID().equals( item.getValue() );
	}
}

