package debugger;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Scrollbar;

import javax.swing.*;
import javax.swing.JScrollPane.*;

public class debugWindow extends JFrame{
	//現在表示中のもの
	private debugObject current_obj;
	//デバッグオブジェクトの管理者
	private debugObjectManager debugObjs = new debugObjectManager();

	//画面の上下切り分け
	private JSplitPane splitcomp = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
	//ＴＡＢ
	private JTabbedPane tabcomp = new JTabbedPane();

	//
	private JPanel icons_pane = new JPanel();
	//実行ボタン
	private JToggleButton play_button = new JToggleButton("実行中");
	
	//実行してよいかどうかのフラグ
	private boolean running_flag;

	/**
	 * シングルトンのため、プライベート コンストラクタ
	 */
	private debugWindow(){
	}
	static private debugWindow _this;
	
	/** シングルトン。
	 * 
	 * @return デバッグウインドウオブジェクトを返す
	 */
	public static debugWindow getInstance(){
		if(_this ==null){
			_this = new debugWindow();
		}
		return _this;
	}
	
	/** 初期化
	 */
	public void init(){

		this.setName("debugWindow");
		//this.setSize(200,480);
		this.setBounds(640,20,290,480);

		this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);

		setLayout(new BorderLayout());


		//実行ボタン等の部分の初期化
		icons_pane.setLayout(new BorderLayout() );
		icons_pane.add(play_button);
		
		
		//上下きりわけの設定
		this.splitcomp.setRightComponent(tabcomp);
		this.splitcomp.setLeftComponent( icons_pane );
		this.splitcomp.setDividerSize(0);
		this.splitcomp.setDividerLocation(30);
		this.splitcomp.setEnabled(false);
		this.add(splitcomp);
		this.setVisible(true);	
	}
	
	
	/** デバッグするオブジェクトをセット
	 * @param name オブジェクト名
	 * @param obj デバッグするオブジェクト
	 */
	public void setObject(String name,Object obj){
		JPanel comp = null;
		debugObject tmp = null;
		if( debugObjs.isMember(obj)==null ){ // 無ければ、追加する
			comp = new JPanel();
			comp.setLayout(new BorderLayout());
			tmp = new debugObject(name,obj , comp);
			this.tabcomp.add(comp,name);
			debugObjs.add( tmp,obj);
			this.current_obj = tmp;
		}
	}

	/** デバッグ対象となるオブジェクトをセット
		* @param obj オブジェクトの値を入れる
		*/
	public void setCurrent(Object obj){
		this.current_obj = debugObjs.isMember(obj);
	}

	/** オブジェクトを消す
	 * @param obj デバッグを行っていたオブジェクト
	 */
	public void removeObject(Object obj){
		debugObjs.remove(this.tabcomp , obj );
	}
	
	
	/** 変数の追加
	 * @param name 変数の名前
	 * @param type 変数の型
	 * @param val 変数の値
	 * @param arr 配列の次元
	 */
	public void addVar(String name,int type,Object val,int arr){
		if(current_obj==null){
			return;
		}
		this.current_obj.addVar( new debugVar(name,type,val,arr) );	
	}
	 
	/** カレント変数をトップにする
	 * 変数のアップデート/取得は追加した順にお願いします。
	 */
	public void iterateVarStart(){
		if(current_obj==null){
			return;
		}
		this.current_obj.iterateVarStart();
	}

	/** 変数のアップデートを行い次の変数へ移動する
	 * 
	 * @param obj 変数にセットする値
	 */
	public void updateVar(Object obj){
		if(current_obj==null){
			return;
		}
		this.current_obj.updateVar(obj);
	}
	
	/** 変数を返し、次の変数へ移動する
	 * @return 変数ＯＢＪ
	 */
	public debugVar getVar(){
		if(current_obj==null){
			return null;
		}
		return this.current_obj.getVar();
	}
	
	/** 変数をINT型とみなし、中身の値を取り出し、次の変数へ移動する
	 * @return 変数のint型の値
	 */
	public int getVarAsInt(){
		if(current_obj==null){
			return 0;
		}
		return this.current_obj.getVarAsInt();		
	}
	
	/** 変数をDOUBLE型とみなし、中身の値を取り出し、次の変数へ移動する
	 * @return 変数のdouble型の値
	 */
	public double getVarAsDouble(){
		if(current_obj==null){
			return 0;
		}
		return this.current_obj.getVarAsDouble();				
	}
	

	/** 変数をfloat型とみなし、中身の値を取り出し、次の変数へ移動する
	 * @return 変数のfloat型の値
	 */
	public float getVarAsFloat(){
		if(current_obj==null){
			return 0;
		}
		return this.current_obj.getVarAsFloat();				
	}
	
	/** 変数をString型とみなし、中身の値を取り出し、次の変数へ移動する
	 * @return 変数のString型の値
	 */
	public String getVarAsString(){
		if(current_obj==null){
			return null;
		}
		return this.current_obj.getVarAsString();		
	}
	
	/** 変数をchar型とみなし、中身の値を取り出し、次の変数へ移動する
	 * @return 変数のchar型の値
	 */
	public char getVarAsChar(){
		if(current_obj==null){
			return 0;
		}
		return this.current_obj.getVarAsChar();				
	}
	
	/** 変数をバイト型とみなし、中身の値を取り出し、次の変数へ移動する
	 * @return 変数のbyte型の値
	 */
	public byte getVarAsByte(){
		if(current_obj==null){
			return 0;
		}
		return this.current_obj.getVarAsByte();		
	}
	
	/** 変数をObject型とみなし、中身の値を取り出し、次の変数へ移動する
	 * @return 変数のObject型の値
	 */
	public Object getVarAsObject(){
		if(current_obj==null){
			return null;
		}
		return this.current_obj.getVarAsObject();
	}

	/** 変数をboolean型とみなし、中身の値を取り出し、次の変数へ移動する
	 * @return 変数のboolean型の値
	 */
	public boolean getVarAsBoolean(){
		if(current_obj==null){
			return false;
		}
		return this.current_obj.getVarAsBoolean();		
	}
  

	/** 変数一覧を描画します
	 */
	public void draw(){
		boolean now_state = !this.play_button.isSelected();

		if( now_state != this.running_flag ){
			if(now_state){
				this.play_button.setText("実行中");
			}else{
				this.play_button.setText("停止中");
			}
			this.setRunningFlag(now_state);
		}
		//今のオブジェクトが空なら描画しない
		if(current_obj==null){
			return;
		}
		try{
			this.debugObjs.getSelected(tabcomp).draw(this.running_flag);
		}catch(Exception e){
		}
	}

	/** 実行フラグのセット
	 * @param flag フラグのセット
	 */
	public void setRunningFlag(boolean flag){

		this.running_flag = flag;
		if(current_obj==null){
			return;
		}
		this.current_obj.setRunningFlag(flag);
	}
	
	/** 実行中かどうかを返す 
	 * @return
	 */
	public boolean getRunningFlag(){
		return this.running_flag;
	}
}
