/*
 * "Peko" Visual Novel System
 *
 * All Rights Reserved.
 * Copyright (c) 1999-2003 Tsukuba Bunko.
 *
 * $Id: TextCoordinator.java,v 1.1.2.3 2003/12/17 10:31:11 ppoi Exp $
 */
package tsukuba_bunko.peko.scenario.text;

import	java.awt.Dimension;

import	java.awt.font.LineBreakMeasurer;
import	java.awt.font.TextAttribute;
import	java.awt.font.TextLayout;

import	java.text.AttributedString;

import	tsukuba_bunko.peko.Logger;

import	tsukuba_bunko.peko.canvas.text.Line;
import	tsukuba_bunko.peko.canvas.text.Page;

import	tsukuba_bunko.peko.resource.ResourceManager;

import	tsukuba_bunko.peko.scenario.Coordinator;
import	tsukuba_bunko.peko.scenario.SceneContext;


/**
 * TextCanvas への操作を取り持つコーディネータモジュールです。
 * @author	$Author: ppoi $
 * @version	$Revision: 1.1.2.3 $
 */
public class TextCoordinator	extends Coordinator	{

	/**
	 * Page の設定を行ったかどうか
	 */
	protected boolean	_pageConfigured = false;

	/**
	 * 行間隔
	 */
	protected float	_lineSpan = 0f;

	/**
	 * 最終行
	 */
	protected Line	_lastLine = null;


	/**
	 * Dimension cache
	 */
	protected Dimension	_sizeCache = new Dimension();


	/**
	 * <code>TextCoordinator</code> のインスタンスを生成します。
	 */
	public TextCoordinator()
	{
		super();
	}


	public void prepare( SceneContext context, Thread activeThread )
	{
		super.prepare( context, activeThread );
		_pageConfigured = false;
		_lastLine = null;
	}


	/**
	 * TextCanvas への操作を開始します。
	 */
	public void begin()
	{
		if( isActiveThread() )	{
			_lastLine = null;
			getActionControler().setSaveEnabled( true );
		}
	}

	/**
	 * TextCanvas への操作を終了し、キャンバスの状態を確定します。
	 */
	public void commit()
	{
		if( isActiveThread() )	{
			getActionControler().setSaveEnabled( false );
			getCurrentPage().commit();
		}
	}

	/**
	 * 表示する文章を TextCanvsa に送信します。
	 * @param	text	表示する文章
	 */
	public void pushText( String text )
	{
		if( !isActiveThread() )	{
			return;
		}

		Page	page = getCurrentPage();
		if( !_pageConfigured )	{
			PageConfigurator.configure( page, getSceneContext() );
			_pageConfigured = true;
			_lineSpan = getLineSpan();
		}

		int	length = text.length();
		if( length == 0 )	{
			Logger.debug( "[scnario.text] empty string is pecified." );
			return;
		}

		if( _lastLine != null )	{
			text = _lastLine.getText() + text;
			length = text.length();
		}
		Logger.debug( text );

		AttributedString	astring = new AttributedString( text );
		astring.addAttribute( TextAttribute.FONT, page.getDefaultFont() );
		astring.addAttribute( TextAttribute.FOREGROUND, page.getForeground() );

		LineBreakMeasurer	lbm = new LineBreakMeasurer( astring.getIterator(), page.getFontRenderContext() );
		float	maxWidth = page.getMaxLineWidth();
		float	lineSpan = _lineSpan;
		boolean	conflictWait = false;
		TextLayout	layout = null;
		Line	line = null;

		layout = lbm.nextLayout( maxWidth );
		line = new Line();
		line.setTextLayout( layout );
		line.setText( text.substring(0, lbm.getPosition()) );
		line.setForeground( page.getForeground() );
		line.setShadowColor( page.getShadow() );

		if( _lastLine == null )	{
			if( isActiveThread() )	{
				line.setLineSpan( lineSpan );	//	ホントはここで margin-top を設定するデス。
				if( !page.isAdaptive(line) )	{
					page = advancesNewPage();
				}
				page.addLine( line );
			}
			else	{
				return;
			}
		}
		else	{
			line.setLineSpan( lineSpan );
			if( isActiveThread() )	{
				page.setLine( (page.getLineCount() - 1), line );
				if( _lastLine.getText().equals(line.getText()) )	{
					conflictWait = true;
				}
			}
			else	{
				return;
			}
		}
		_lastLine = line;

		int	lastLinePosition = 0;
		while( (lastLinePosition = lbm.getPosition()) < length )	{
			line = new Line();
			line.setTextLayout( lbm.nextLayout(maxWidth) );
			line.setLineSpan( lineSpan );
			line.setText( text.substring(lastLinePosition, lbm.getPosition()) );
			line.setForeground( page.getForeground() );
			line.setShadowColor( page.getShadow() );
			if( isActiveThread() )	{
				if( !page.isAdaptive(line) )	{
					if( conflictWait )	{
						conflictWait = false;
					}
					else	{
						page.updateContents();
						stop();	//	ここー！
					}
					page = advancesNewPage();
				}
				if( page != null )	{
					page.addLine( line );
					conflictWait = false;
				}
				else	{
					return;
				}
				_lastLine = line;
			}
			else	{
				return;
			}
		}
		if( isActiveThread() )	{
			page.updateContents();
		}
	}

	/**
	 * 現在表示中のページを取得します。
	 * @return	現在表示中のページ
	 */
	public Page getCurrentPage()
	{
		return getCanvasManager().getCurrentPage();
	}

	/**
	 * 新しいページに切り替え、新しいページを取得します。
	 * @return	新しいページ
	 */
	public Page advancesNewPage()
	{
		if( isActiveThread() )	{
			return getCanvasManager().advancesNewPage();
		}
		else	{
			return null;
		}
	}

	/**
	 * 処理を一時停止します。
	 */
	protected void stop()
	{
		if( isActiveThread() )	{
			getActionControler().stop();
		}
	}

	/**
	 * 行間隔を取得します。
	 * @return	行間隔
	 */
	protected float getLineSpan()
	{
		SceneContext	context = getSceneContext();
		String	value = context.getProperty( PropertyIDs.CANVAS_TEXT_LINESPAN );
		if( value != null )	{
			try	{
				return Float.parseFloat( value );
			}
			catch( Exception e )	{
				Logger.warn( MessageIDs.SCN2002W, e );
			}
		}

		ResourceManager	resources = ResourceManager.getInstance();
		Float	lineSpan = (Float)resources.getResource( ResourceIDs.CANVAS_TEXT_LINESPAN );
		if( lineSpan != null )	{
			return lineSpan.floatValue();
		}
		else	{
			Logger.warn( MessageIDs.SCN2001W, new Object[]{"20.0"} );
			return 20f;
		}
	}
}