/*
 * "Peko" Visual Novel System
 *
 * All Rights Reserved.
 * Copyright (c) 1999-2003 Tsukuba Bunko.
 *
 * $Id: Stage.java,v 1.1.2.1 2003/12/11 10:23:10 ppoi Exp $
 */
package tsukuba_bunko.peko.canvas.stage;

import	java.awt.Color;
import	java.awt.Image;

import	java.io.Serializable;

import	java.util.HashMap;
import	java.util.Iterator;
import	java.util.Map;

import	tsukuba_bunko.peko.Logger;

import	tsukuba_bunko.peko.resource.ColorManager;


/**
 * 舞台を表示するキャンバスです。
 * @author	$Author: ppoi $
 * @version	$Revision: 1.1.2.1 $
 */
public class Stage	implements Serializable	{

	/**
	 * このステージを描画する StageCanvas
	 */
	transient private StageCanvas	_canvas = null;

	/**
	 * 音楽を再生する AudioPlayer
	 */
	private AudioPlayer	_audioPlayer = new AudioPlayer();


	/**
	 * 登場人物
	 */
	transient private Map	_actors = new HashMap();

	/**
	 * 確定した登場人物
	 */
	private HashMap	_committedActors = new HashMap();

	/**
	 * 背景
	 */
	transient private String	_background = null;

	/**
	 * 確定した背景
	 */
	private String	_committedBackground = null;

	/**
	 * 背景画像
	 */
	transient private Image	_backgroundImage = null;

	/**
	 * 背景色
	 */
	transient private Color	_backgroundColor = null;

	/**
	 * 確定した背景色
	 */
	private Color	_committedBackgroundColor = null;

	/**
	 * スライド名
	 */
	transient private String	_slide = null;

	/**
	 * 確定したスライド名
	 */
	private String	_committedSlide = null;

	/**
	 * スライド画像
	 */
	transient private Image	_slideImage = null;


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


	/**
	 * 人物を舞台に登場させます。
	 * @param	actor	人物
	 */
	public void enter( Actor actor )
	{
		_actors.put( actor.getName(), actor );
	}

	/**
	 * 人物を取得します。
	 */
	public Actor getName( String name )
	{
		return (Actor)_actors.get( name );
	}

	/**
	 * 人物を舞台から退場させます。
	 */
	public Actor exit( String name )
	{
		Actor	actor = (Actor)_actors.remove( name );
		if( actor != null )	{
			actor.disposeLooks();
		}
		return actor;
	}

	/**
	 * 全ての人物を舞台から退場させます。
	 */
	public void exitAll()
	{
		String[]	names = (String[])_actors.keySet().toArray( new String[_actors.size()] );
		for( int i = 0; i < names.length; ++i )	{
			exit( names[i] );
		}
	}

	/**
	 * 人物を取得します。
	 */
	public Actor getActor( String name )
	{
		return (Actor)_actors.get( name );
	}

	/**
	 * 人物リストを取得します。
	 */
	public Map getActors()
	{
		return _actors;	//	クローニングした方が良いかも？
	}

	/**
	 * 背景画像を設定します。このメソッドを呼び出すと、背景色は null に設定されます。
	 * @param	image	背景画像
	 */
	public void setBackgroundImage( String image )
	{
		ImageManager	images = ImageManager.getInstance();
		if( (_backgroundImage != null) && !_background.equals(image)  )	{
			images.putImage( _background, _backgroundImage );
			_backgroundImage = null;
		}

		Image	background = images.getImage( image );
		if( background != null )	{
			_backgroundImage = background;
			_background = image;
			_backgroundColor = null;
		}
		else if( background == null )	{
			Logger.error( "[canvas.stage] invalid background-image :" + image );
			_backgroundColor = Color.black;
			_background = "black";
		}
	}

	/**
	 * 背景画像を取得します。
	 * @return	背景画像
	 */
	public Image getBackgroundImage()
	{
		return _backgroundImage;
	}

	/**
	 * 背景色を設定します。このメソッドを呼び出すと、背景画像は null に設定されます。
	 * @param	color	背景色
	 */
	public void setBackgroundColor( String color )
	{
		if( _backgroundImage != null )	{
			ImageManager	images = ImageManager.getInstance();
			images.putImage( _background, _backgroundImage );
			_backgroundImage = null;
		}
		ColorManager	colors = ColorManager.getInstance();
		_backgroundColor = colors.getColor( color );
		_background = color;
	}

	/**
	 * 背景色を取得します。
	 * @return	背景色
	 */
	public Color getBackgroundColor()
	{
		return _backgroundColor;
	}

	/**
	 * スライドを表示します。
	 * @param	slide	スライド名
	 */
	public void showSlide( String slide )
	{
		ImageManager	images = ImageManager.getInstance();
		if( (_slide != null) && !_slide.equals(slide) )	{
			images.putImage( _slide, _slideImage );
		}
		_slideImage = images.getImage( slide );
		_slide = slide;
	}

	/**
	 * スライドを隠します。
	 */
	public void hideSlide()
	{
		if( _slideImage != null )	{
			ImageManager	images = ImageManager.getInstance();
			images.putImage( _slide, _slideImage );
		}
		_slide = null;
		_slideImage = null;
	}

	/**
	 * スライド名を取得します。
	 * @return	スライド名
	 */
	public String getSlide()
	{
		return _slide;
	}

	/**
	 * スライド画像を取得します。
	 * @return	スライド画像
	 */
	public Image getSlideImage()
	{
		return _slideImage;
	}

	/**
	 * BGM を再生します。
	 * @param	id	BGM ID
	 * @param	clipName	クリップ名
	 * @param	loop	ループする場合は <code>true</code>、しない場合は <code>false</code>
	 */
	public void playBGM( String id, String clipName, boolean loop )
	{
		_audioPlayer.playBGM( id, clipName, loop );
	}

	/**
	 * BGM を停止します。
	 * @param	id	停止する BGM の ID
	 */
	public void stopBGM( String id )
	{
		_audioPlayer.stop( id );
	}

	/**
	 * SE を停止します。
	 * @param	id	停止する SE の ID
	 */
	public void stopSE( String id )
	{
		_audioPlayer.stop( id );
	}

	/**
	 * SE を再生します。
	 * @param	id	SE ID
	 * @param	clipName	クリップ名
	 * @param	loop	ループする場合は <code>true</code>、しない場合は <code>false</code>
	 */
	public void playSE( String id, String clipName, boolean loop )
	{
		_audioPlayer.playSE( id, clipName, loop );
	}

	/**
	 * サウンド効果を処理するオーディオプレーヤーを設定します。
	 * @param	audioPlayer	オーディオプレーヤー
	 */
	public void setAudioPlayer( AudioPlayer audioPlayer )
	{
		_audioPlayer = audioPlayer;
	}

	/**
	 * サウンド効果を処理するオーディオプレーヤーを取得します。
	 * @return	オーディオプレーヤー
	 */
	public AudioPlayer getAudioPlayer()
	{
		return _audioPlayer;
	}

	/**
	 * このステージを描画するキャンバスを設定します。
	 * @param	canvas	このステージを描画するキャンバス
	 */
	void setStageCanvas( StageCanvas canvas )
	{
		_canvas = canvas;
	}

	/**
	 * このステージを描画するキャンバスを取得します。
	 * @return	ステージキャンバス
	 */
	public StageCanvas getStageCanvas()
	{
		return _canvas;
	}

	/**
	 * このステージを描画しているキャンバスを最新の状態に更新します。
	 */
	public void updateCanvas()
	{
		_canvas.updateCanvas( null );
	}

	/**
	 * このステージを描画しているキャンバスを最新の状態に更新します。
	 */
	public void updateCanvas( String effect )
	{
		if( _canvas != null )	{
			Logger.debug( "[canvas.stage] effect :" + effect );
			_canvas.updateCanvas( effect );
		}
	}


	public void commit()
	{
		_committedActors.clear();
		_committedActors.putAll( _actors );
		_committedBackground = _background;
		_committedBackgroundColor = _backgroundColor;
		_committedSlide = _slide;
	}

	/**
	 * Stage を破棄します。
	 */
	void dispose()
	{
		Iterator	itr = _actors.values().iterator();
		while( itr.hasNext() )	{
			((Actor)itr.next()).disposeLooks();
		}

		if( _backgroundImage != null )	{
			ImageManager	images = ImageManager.getInstance();
			images.putImage( _background, _backgroundImage );
		}

		_audioPlayer.stopAll();
	}

	/**
	 * Stage を描画する準備を実行します。
	 */
	public void prepare()
	{
		if( _actors == null )	{
			_actors = (Map)_committedActors.clone();
		}

		Iterator	itr = _actors.values().iterator();
		while( itr.hasNext() )	{
			((Actor)itr.next()).prepare();
		}

		if( _committedBackgroundColor == null )	{
			setBackgroundImage( _committedBackground );
		}
		else	{
			_background = _committedBackground;
			_backgroundColor = _committedBackgroundColor;
		}

		if( _committedSlide != null )	{
			showSlide( _committedSlide );
		}

		updateCanvas();
	}
}
