import java.awt.*;
import java.applet.*;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.awt.image.*;
import java.util.StringTokenizer;


//--------------------------------------------------
// 会話用クラス
//--------------------------------------------------
class TalkManage{
	// フォントサイズ
	final int FONT_SIZE = 14;

	// 以下、受け継いだもの

	// グラフィックス
	Graphics g;

	// アプレット
	Applet applet;

	// 会話対象キャラ
	Chara m_target_chara;

	// 会話フェイズ
	int TalkPhase;

	// イベントスクリプト用文字列バッファ
	StringBuffer m_script_sb[];

	// その行数
	int ScriptLineNum;

	// トーク用バッファ
	StringBuffer m_talk_buffer;

	// 現在読んでいるスクリプトのライン
	int NowReadLine;

	// 現在のスクリプトコマンド
	String NowCommand;
	String NextCommand;

	// 表示した会話文字数
	int NowDspTalkLength;

	// 最大文字数
	int MaxTalkLength;

	// カーソル点滅用カウンタ
	int m_next_talk_timer;

	// インスタンス
	static TalkManage m_instance;
	static TalkManage GetInstance(){ return m_instance; }
	static void NewInstance( MapEdit applet ){ m_instance = new TalkManage( applet ); }

	TalkManage( MapEdit applet ){
		this.applet = applet;
	}

	void Initialize(){
		TalkPhase = 0;
		m_script_sb = new StringBuffer[ 256 ];
		m_talk_buffer = new StringBuffer();
		NowReadLine = 0;
		NowCommand = new String("");
		NextCommand = new String("");
		NowDspTalkLength = 0;
		MaxTalkLength = 0;
		m_next_talk_timer = 0;
	}

	void SetTargetChara( Chara chara ){
		m_target_chara = chara;
	}

	//--------------------------------------------------
	// デバッグプリント
	//--------------------------------------------------
	void DebugPrint( String str ){
		System.out.println( str );
	}

	//--------------------------------------------------
	// グラフィックスセット
	//--------------------------------------------------
	void SetGraphics( Graphics g ){
		this.g = g;
	}

	// 会話ウィンドウを半透明で描画
	void DspDrawTalkWindow( int OffPix[] ){
		final int FONT_WIDTH_SIZE = 12;
		final int LINE_WORD_NUM = 19;
		final int START_Y = (MapManage.HEIGHT-70);
		final int START_X = 10;
		// フォントサイズ
		final int FONT_SIZE = 14;

		// 会話コマンドのとき
		if( !NowCommand.equals("#talk") ){ return; }

		Game.GetInstance().fillRectToMemory( OffPix, START_X, START_Y, (MapManage.WIDTH-20) + 1, FONT_SIZE * 4 + 5, 0x80000060 );
	}

	// 会話の文字描画
	void DrawTalkWindow(){
		int i, x, y;

		final int FONT_WIDTH_SIZE = 12;
		final int LINE_WORD_NUM = 19;
		final int START_Y = (MapManage.HEIGHT-70);
		final int START_X = 10;

		// 会話コマンドのとき
		if( !NowCommand.equals("#talk") ){ return; }

		// ウィンドウの枠
		g.setColor( Color.white );
		g.drawRect( START_X - 1, START_Y - 1, (MapManage.WIDTH-20) + 1, FONT_SIZE * 4 + 5 + 1 );

		// 文字の色
		g.setColor( Color.white );

		// １文字ずつ描画
		int dsp_x, dsp_y;
		int start_line;

		x = 0;
		y = 0;

		// 会話の改行の数を数える
		int br_num = 0;
		for( i = 0; i < NowDspTalkLength; i++ ){
			// 改行コードが来たら改行
			if( m_talk_buffer.charAt(i) == '\n' ){
				x = 0;
				y++;
				//i++;
				if( i+1 >= NowDspTalkLength )break;
				continue;
			}
			x++;
			// 一行最大文字数こえたら自動改行（親切設計）
			if( x >= LINE_WORD_NUM ){
				x = 0;
				y++;
			}
		}
		br_num = y;
		int talk_start = br_num - 3;
		if( talk_start < 0 ){ talk_start = 0; }

		x = 0;
		y = 0;
		// 文字MAX行−4行から表示
		for( i = 0; i < NowDspTalkLength; i++ ){
			// 改行コードが来たら改行
			if( m_talk_buffer.charAt(i) == '\n' ){
				x = 0;
				y++;
				//i++;
				if( i+1 >= NowDspTalkLength )break;
				continue;
			}
			dsp_x = START_X + 4 + x * FONT_WIDTH_SIZE;
			if( y >= talk_start ){
				int new_y;
				new_y = y - talk_start;
				if( new_y < 0 ){ new_y = 0; }
				dsp_y = START_Y + FONT_SIZE + new_y * FONT_SIZE;

				// １行LINE_WORD_NUM文字
				g.drawString( String.valueOf( m_talk_buffer.charAt(i) ), dsp_x, dsp_y );
			}
			x++;

			// 一行最大文字数こえたら自動改行
			if( x >= LINE_WORD_NUM ){
				x = 0;
				y++;
			}
		}
		NowDspTalkLength++;

		// 会話終了
		if( NowDspTalkLength > MaxTalkLength ){
			NowDspTalkLength = MaxTalkLength;

			// 続きの会話があるなら、NEXTカーソル
			if( NextCommand.equals("#nextpage") ){
				// 点滅
				if( m_next_talk_timer < 10 ){
					g.drawString( "▼", START_X + 150 - (FONT_SIZE>>1), START_Y + FONT_SIZE * 4 );
				}
				m_next_talk_timer++;
				if( m_next_talk_timer > 20 ){
					m_next_talk_timer = 0;
				}
			}else{
				m_next_talk_timer = 0;
			}
		}
	}

	boolean IsExitTalk(){
		return NowDspTalkLength == MaxTalkLength ? true : false;
	}

	// 会話できる範囲描画
	void DrawCanTalkArea( int px, int py ){
		int i, j;
		int x, y;
		int len;
		final int TALK_LENGTH = 1;

		// 座標系に
		int chara_x = px / MapManage.CHIP_SIZE;
		int chara_y = py / MapManage.CHIP_SIZE;

		// 描画
		g.setColor( Color.cyan );
		for( y = chara_y - TALK_LENGTH; y <= chara_y + TALK_LENGTH; y++ ){
			for( x = chara_x - TALK_LENGTH; x <= chara_x + TALK_LENGTH; x++ ){
				// 主人公との距離が１以内だけ描画
				len = abs( chara_x - x ) + abs( chara_y - y );
				if( len <= TALK_LENGTH && len >= 1 && 
					x >= 0 && y >= 0 && x < MapManage.GetInstance().width && y < MapManage.GetInstance().height ){

					// 移動可能範囲
					Game.GetInstance().LightMapData[ x ][ y ] = 0;

					// 四角形描画
					// スクリーン座標に変換
					g.drawRect( CharaManage.GetInstance().ToScreenX(x*MapManage.CHIP_SIZE) +1,
					CharaManage.GetInstance().ToScreenY( y*MapManage.CHIP_SIZE + 1 ),
					 MapManage.CHIP_SIZE - 2, MapManage.CHIP_SIZE - 2 );
				}
			}
		}
	}

	int abs( int a ){
		return a > 0 ? a : -a;
	}

	// 会話処理
	void TalkAction(){
		switch( TalkPhase ){
		case 0:
			// 初期化
			InitTalk();
			TalkPhase++;
			break;
		case 1:
			// 


			break;
		}
	}

	// 会話初期化
	void InitTalk(){
		// 対応イベントのスクリプトの読み込み
		String file = m_target_chara.GetEvent();

		// スクリプトロード
		if( MapEdit.RELEASE_MODE ){
			ScriptLineNum = LoadEventScript( "map/"+MapEdit.GetMapID()+"/"+file+".txt" + "?" + System.currentTimeMillis() , m_script_sb );
		}else{
			ScriptLineNum = LoadEventScript( "map/"+MapEdit.GetMapID()+"/"+file+".txt", m_script_sb );
		}

		// エラー時
		if( ScriptLineNum == 0 ){
			Game.GetInstance().now_phase = Game.NORMAL_PHASE;
			return;
		}

		NowReadLine = 0;
		AnalyzeScript();
	}

	// スクリプト解析
	void AnalyzeScript(){
		int i;
		String command;

		// トークン分割用クラス
		StringTokenizer st;

		NowCommand = "";

		// 現在の行から解析
		for( i = NowReadLine; i < ScriptLineNum; i++ ){
			//DebugPrint(""+i+"行目" );
			// 頭に#がついてるものがコマンド
			if( m_script_sb[i].length() > 0 && m_script_sb[i].charAt( 0 ) == '#' ){
				command = m_script_sb[i].toString();
				// マップ移動コマンド
				if( command.indexOf("#MoveMap") >= 0 ){
					String next_map = "";
					st = new StringTokenizer( command, " " );
					// 引数確認
					if( st.hasMoreTokens() ) NowCommand = st.nextToken();
					if( st.hasMoreTokens() ) next_map = st.nextToken();
					if( st.hasMoreTokens() ) Game.GetInstance().m_next_x = Integer.parseInt( st.nextToken() );
					if( st.hasMoreTokens() ) Game.GetInstance().m_next_y = Integer.parseInt( st.nextToken() );

					// マップ切り替え
					Game.GetInstance().SubPhase = 0;
					Game.GetInstance().now_phase = Game.CHANGE_MAP_PHASE;
					Game.GetInstance().m_next_map_id = next_map;
					// スクリプトを終える
					break;
				}
				// バトルコマンド
				else if( command.indexOf("#EnCount") >= 0 ){
					// エンカウント開始
					Game.GetInstance().EnCountInit();
					// スクリプトを終える
					break;
				}
				// 会話コマンド開始
				else if( command.equals("#talk") ){
					NowDspTalkLength = 0;
					NowCommand = command;
				}
				// 今までが会話なら一旦終了
				else if( NowCommand.equals("#talk") ){
					// 会話の続きある？
					if( command.equals( "#nextpage" ) ){
						// 次回のコマンド格納
						NextCommand = m_script_sb[i].toString();
					}
					// 次回はここから
					NowReadLine = i;
					break;
				}
				// 次のページの場合
				else if( command.equals("#nextpage") ){
					//m_talk_buffer.delete( 0, MaxTalkLength );

					// 初期化
					// NowDspTalkLength = 0;

					// コマンドをtalkにしておく
					NowCommand = "#talk";
				}else{
					NowCommand = command;
				}
			}else{
				// 会話の場合、追加していく
				if( NowCommand.equals("#talk") ){
					//DebugPrint( "i="+i+"nai="+m_script_sb[i].toString() );
					m_talk_buffer.append( m_script_sb[i].toString() );
					m_talk_buffer.append( "\n" );
				}
			}
		}

		// 会話の場合
		if( NowCommand.equals("#talk") ){
			// 会話初期化
			MaxTalkLength = m_talk_buffer.length();
		}

		// 最後まで読みきっていた場合
		if( i == ScriptLineNum ){
			// エラーチェック


			NextCommand = "";
		}

	}

	//--------------------------------------------------
	// イベントスクリプト読み込み
	//--------------------------------------------------
	int LoadEventScript( String file, StringBuffer sb[] ){
		DebugPrint( file );

		try{
			InputStream is = new URL( applet.getDocumentBase(), file ).openStream();

			// テキストだからリーダーを使う
			BufferedReader br = new BufferedReader( new InputStreamReader( is ) );

			// ライン格納
			String line;

			int i;
			DebugPrint( "script_load_start" );

			// 一行ずつ読み込む
			int line_num = 0;
			while( ( line = br.readLine() ) != null ){
				// コメント（;で始まるもの）は虫
				if( line.length() > 0 && line.charAt( 0 ) == ';' ){
					continue;
				}

				// バッファに追加していく（StringBufferは軽いはず…）
				sb[line_num] = new StringBuffer();
				sb[line_num].append( line );
				line_num++;
			}
			is.close();
			return line_num;
		}catch( IOException e ){
			DebugPrint( "load_fail" );
			return 0;
		}
	}

}
