#define DEBUG 0
/* 
	TOWNS囲碁棋譜記録プログラム
	                                      1992/02/25  久保田俊也

	91/02/25  kifuctrl モジュールを本体より分離 
				kifuデ−タを操作する関数の集まり 

*/
#include <stdio.h>
#include <stdlib.h>
#include "igo.h"
#include "banx.h"
#include "kiffile.h"
#include "kifuctrl.h"
#include "title.h"
#include "print.h"

#define HEAD -1 /* ichiが-1の場合HEADとする */
#define SPACE20 "                    "

char *comment_read(int comment_no);
TE *cell_get();
TE_ARG cell_read();

static TE *current_te;
static TE *head;
static char ban[MAX_BANSIZE2];
static BAN_TYPE ban_type;
static int bansize;
static int bansize2;

static int  numberdisp_flg = 1;	/* 手順表示する 0以外 しない 0 */
static int  repeat_flg = 0;		/* リピ−トする 0以外 しない 0 */
static int  change_flg = 0; 	/* 変化再生する 0以外 しない 0 */
static int  comment_flg = 1;	/* コメント表示する 0以外 しない 0 */
static int	save_rebirth_speed = 0;


int kifu_init()
{
int i;

/* bansize等ここでは使わないが他のモジュ−ルで使用 */
	ban_type = *title_bantype_read();
	if( ban_type.type == NORMAL){
		bansize = ban_type.size;
		bansize2 = (bansize+1)*(bansize+2)+1;
	}

	cell_init();
	head = cell_get();

	comment_init();
	banx_init( ban);

	head->iro = WHITE;
	for(i=0;i<bansize2;i++){
		head->ban[i] = ban[i];
	}
	head->brother = head;
	head->prev    = head;
	head->next    = head;
	head->ichi    = HEAD; 	/* headの判定使用*/
	head->black_capture_number = 0;
	head->white_capture_number = 0;

	current_te   = head;
	return 0;
}

int kifu_put(int ichi)
{
int i, uchiage_number;
TE *add_te;
TE *temp;

	if(ban[ichi]==BLACK || ban[ichi]==WHITE){
		return 0;
	}

	if(current_te->next->iro == DELETE){
		add_te = current_te->next;
	}else{
		add_te = cell_get();
		if(add_te == NULL){
			printf("return of cell_get() = null!\n");
			return 1;
		}
		add_te->comment = 0;
		/*  次の手に兄弟がない */
		if(current_te->next == current_te->next->brother){
			add_te->brother = add_te;
		/*  次の手が枝の頭ではない */
		}else if(current_te->next->ichi != HEAD){
			add_te->brother = current_te->next->brother;
			for(temp=current_te->next;
				temp->brother != current_te->next;
				temp=temp->brother){
				;
			}
			current_te->next->brother = temp->brother;
			temp->brother = add_te;
		/*  次の手が枝の頭で かつ 一番下の弟である */
		}else if(current_te->next->brother->ichi != HEAD ||
		         current_te->next->brother == head){
			add_te->brother = add_te;
		/*  次の手が枝の頭で かつ 下に弟がいる */
		}else{
			add_te->brother = current_te->next->brother;
			for(temp=current_te->next;
				temp->brother->ichi == HEAD && temp->brother != head;
				temp=temp->brother){
				;
			}
			current_te->next->brother = temp->brother;
			temp->brother = add_te;
		}
		
		add_te->prev = current_te;
		add_te->next = current_te->next;
		current_te->next->prev = add_te;
		current_te->next       = add_te;
	}

	ban[ichi] = 1 - current_te->iro;
	banx_uchiage( ban, ichi, &uchiage_number);
	Debugprint2("uchiga_number = %d\n", uchiage_number);
	
	add_te->ichi = ichi;
	add_te->iro  = 1 - current_te->iro;
	for(i=0;i<bansize2;i++){
		add_te->ban[i] = ban[i];
	}
	if(add_te->iro == BLACK){
		add_te->black_capture_number = current_te->black_capture_number + uchiage_number;
		add_te->white_capture_number = current_te->white_capture_number;
	}else{
		add_te->black_capture_number = current_te->black_capture_number;
		add_te->white_capture_number = current_te->white_capture_number + uchiage_number;
	}

	
	current_te = add_te;
	return 0;

}

int kifu_cancel()
{
int i;
TE *save_te;

    if(current_te->ichi == HEAD || current_te->iro == DELETE){
		return -1;
	}

	if(current_te->brother != current_te || current_te->comment != 0){
		current_te->iro = DELETE;
		current_te = current_te->prev;
	}else{
		current_te->prev->next = current_te->next;
		current_te->next->prev = current_te->prev;
		save_te = current_te->prev;
		cell_free(current_te);
		current_te = save_te;
	}
	
	for(i=0;i<bansize2;i++){
		ban[i] = current_te->ban[i];
	}
	return 0;
}

int kifu_forward()
{
int i, uchiage_number;
TE *wk_te;
TE *save_te;

	save_te = current_te;
	do{
		current_te = current_te->next;
		if( change_flg != 0){
			if(current_te != current_te->brother){
				current_te = current_te->brother;
			}
		}
	}while(current_te->iro==DELETE);
	
	if(current_te->ichi==HEAD){
		if(repeat_flg == 0 && change_flg == 0){
			current_te = save_te;
			return REPEAT_CANNOT_BOTTOM_CELL;
		}
		
		if(current_te==head){
			if(repeat_flg == 0){
				current_te = save_te;
				return REPEAT_CANNOT_BOTTOM_CELL;
			}
		
			for(i=0;i<bansize2;i++){
				ban[i] = current_te->ban[i];
			}
			return HEAD_CELL;
		}else{
			for(i=0;i<bansize2;i++){
				if(change_flg == 0){
					ban[i] = current_te->ban[i];
				}else{
					current_te->ban[i] = ban[i];
					current_te->black_capture_number = save_te->black_capture_number;
					current_te->white_capture_number = save_te->white_capture_number;
				}
			}
			return BOTTOM_CELL;
		}
	}else{
		/* 打ち上げ処理を行うために前の画面に戻る */
		for(wk_te=current_te->prev;wk_te->iro==DELETE;wk_te=wk_te->prev){
			;
		}
		for(i=0;i<bansize2;i++){
			ban[i] = wk_te->ban[i];
		}
		
		ban[current_te->ichi] = current_te->iro;
		banx_uchiage( ban, current_te->ichi, &uchiage_number);
		if(current_te->iro == BLACK){
			current_te->black_capture_number = wk_te->black_capture_number + uchiage_number;
			current_te->white_capture_number = wk_te->white_capture_number;
		}else{
			current_te->black_capture_number = wk_te->black_capture_number;
			current_te->white_capture_number = wk_te->white_capture_number + uchiage_number;
		}
		for(i=0;i<bansize2;i++){
			current_te->ban[i] = ban[i];
		}
		return NORMAL_CELL;
	}

}

int kifu_back()
{
int i;
TE *wk_te;

	if(repeat_flg == 0 && change_flg == 0){
		if(current_te->ichi == HEAD){
			for(i=0;i<bansize2;i++){
				ban[i] = current_te->ban[i] ;
			}
			return 0;
		}
	
	}else if(repeat_flg == 0 && change_flg != 0){
		if(current_te == head){
			for(i=0;i<bansize2;i++){
				ban[i] = current_te->ban[i] ;
			}
			return 0;
		}
	}
	
	do{
		if(change_flg != 0){
			if(current_te->brother!=current_te){
				for(wk_te=current_te;wk_te->brother!=current_te;wk_te=wk_te->brother){
					;
				}
				current_te = wk_te;
			}
		}
		current_te = current_te->prev;
	}while(current_te->iro==DELETE);
	
	
	for(i=0;i<bansize2;i++){
		ban[i] = current_te->ban[i] ;
	}

	return 0;
}

int kifu_first()
{
int i;
	
	if(change_flg != 0){
		current_te = head;
		for(i=0;i<bansize2;i++){
			ban[i] = head->ban[i] ;
		}
	}else{
		for(current_te=current_te->next;current_te->ichi!=HEAD;current_te=current_te->next){
			;
		}

		for(i=0;i<bansize2;i++){
			ban[i] = current_te->ban[i];
		}
	}
	return 0;
}

int kifu_read(char fname[])
{
int i;
int handy, te_number;

TE_ARG		kiffile_te2;

	if(kiffile_read(fname) == -1){
		return -1;
	}

	kifu_init(); /* ファイルリ−ドの後に実行 */
	kiffile_comment_read();
	disp_init();
	banx_init( ban);
	current_te = head;

	if((handy = title_handy_read()) != 0){
		if(banx_handy_set( ban, handy)!=0){
			return -1;
		}
		head->iro = BLACK;
	}else{
		head->iro = WHITE;
	}
	for(i=0;i<bansize2;i++){
		head->ban[i] = ban[i];
	}

	te_number= title_tenumber_read();
	for(i=1;i <= te_number;i++){
		kifte_read2(&kiffile_te2);
		if(cell_write(kiffile_te2)== -1){
			printf("cell_write error = %d!\n", te_number);
			return -1;
		}
	}
		
	if(cell_write_finish()== -1){
		printf("cell_write error = %d!\n", te_number);
		return -1;
	}
		

	return 0;
}

int kifu_write(char fname[])
{
TE_ARG  	kiffile_te;

	kiftitle_write();

	kiffile_te = cell_read();
	while(kiffile_te.no != -1){
		kifte_write(kiffile_te);
		kiffile_te = cell_read();
	}
	if(kiffile_write(fname) != 0){
		return -1;
	}
	
	return 0;
}

int kifu_handy(int handy)
{
int i;
BAN_TYPE ban_type;

	ban_type = *title_bantype_read();

	if( ban_type.type == NORMAL && ban_type.size == 19){
		;
	}else{
		return -1;
	}

	kifu_init();
	if(banx_handy_set( ban, handy ) == 0){
		for(i=0;i<bansize2;i++){
			head->ban[i] = ban[i];
		}
		title_handy_set(handy);
		head->iro = BLACK;
		current_te = head;
		return 0;
	}else{
		return -1;
	}
}

int kifu_disp()
{
int i;
TE *wk_te;
int ex_ban[MAX_BANSIZE2];

	for(i=0;i<bansize2;i++){
		ex_ban[i] = 0;
	}
	
	if(numberdisp_flg != 0){
		for(wk_te=current_te;wk_te->prev->ichi!=HEAD;wk_te=wk_te->prev){
			;
		}
		
		i=1;
		for(;wk_te!=current_te->next;wk_te=wk_te->next){
			if(wk_te->iro != DELETE){
				ex_ban[wk_te->ichi] = i;
				i++;
			}
		}
	}
	disp_te(ban,ex_ban);
	return 0;
}

int kifu_numberdisp()
{
	numberdisp_flg = 1-numberdisp_flg;
	return 0;
}

int kifu_judge(int *b_territory_number, int *w_territory_number)
{
	banx_judge(ban);
	banx_disp();

	*b_territory_number=0;
	*w_territory_number=0;

	banx_territory(b_territory_number, w_territory_number);
	*b_territory_number += current_te->black_capture_number;
	*w_territory_number += current_te->white_capture_number;
	return 0;
}

int kifu_judgeput(int ichi, int *b_territory_number, int *w_territory_number)
{

	banx_put(ichi);
	banx_disp();

	*b_territory_number=0;
	*w_territory_number=0;

	banx_territory(b_territory_number, w_territory_number);
	*b_territory_number += current_te->black_capture_number;
	*w_territory_number += current_te->white_capture_number;

	return 0;
}

int kifu_abandon()
{
int i;
int comment_no;
TE *add_te;
TE *temp;

	if(current_te->next->iro == DELETE){
		add_te = current_te->next;
	}else{
		add_te = cell_get();
		if(add_te == NULL){
			printf("return of cell_get() = null!\n");
			return 1;
		}
		add_te->comment = 0;
		/*  次の手に兄弟がない */
		if(current_te->next == current_te->next->brother){
			add_te->brother = add_te;
		/*  次の手が枝の頭ではない */
		}else if(current_te->next->ichi != HEAD){
			add_te->brother = current_te->next->brother;
			for(temp=current_te->next;
				temp->brother != current_te->next;
				temp=temp->brother){
				;
			}
			current_te->next->brother = temp->brother;
			temp->brother = add_te;
		/*  次の手が枝の頭で かつ 一番下の弟である */
		}else if(current_te->next->brother->ichi != HEAD ||
		         current_te->next->brother == head){
			add_te->brother = add_te;
		/*  次の手が枝の頭で かつ 下に弟がいる */
		}else{
			add_te->brother = current_te->next->brother;
			for(temp=current_te->next;
				temp->brother->ichi == HEAD && temp->brother != head;
				temp=temp->brother){
				;
			}
			current_te->next->brother = temp->brother;
			temp->brother = add_te;
		}
		
		add_te->prev = current_te;
		add_te->next = current_te->next;
		add_te->black_capture_number = current_te->black_capture_number;
		add_te->white_capture_number = current_te->white_capture_number;
		current_te->next->prev = add_te;
		current_te->next       = add_te;
	}

	add_te->ichi = 0; /* 着手放棄の時設定 0正しい ? */
	add_te->iro  = 1 - current_te->iro;
	for(i=0;i<bansize2;i++){
		add_te->ban[i] = ban[i];
	}

	current_te = add_te;

	comment_no = comment_set("着手放棄");
	current_te->comment = (short int)comment_no;

	return 0;
}

int kifu_print(int start_te, int end_te, int out_start_te, int with_comment_id)
{
int i,j, uchiage_number;
int x,y;
int h_ichi;
TE *wk_te;
char print_ban[MAX_BANSIZE2];
int ex_print_ban[MAX_BANSIZE2];
char wstr[500];
char wstr2[33];

	Debugprint("kifu_print start!\n");
	wstr[0] = '\0';
	for(i=0;i<bansize2;i++){
		print_ban[i] = head->ban[i];
		ex_print_ban[i] = 0;
	}

	/*　最初の盤面を設定*/
	/*　初期値の手が存在する事のチェックをどう行うか　*/
	/*　画面より先の手を指定された場合の打ち上げ処理の実行　*/
	wk_te=head->next;
	for(i=1;i<start_te;){
		if(wk_te->next == head){
			return -1; /* 初期値の手が存在しない　*/
		}

		if(wk_te->iro != DELETE){
			print_ban[wk_te->ichi] = wk_te->iro;
			banx_uchiage( print_ban, wk_te->ichi, &uchiage_number);
			i++;
		}
		wk_te=wk_te->next;
	}

	Debugprint("kifu_print ban_setti ok !\n");
	/* 手順の設定　*/
	j=out_start_te;
	for(i=start_te;i<=end_te;i++){
		if(wk_te->iro != DELETE){
			if(print_ban[wk_te->ichi] == BLANK){
				print_ban[wk_te->ichi] = wk_te->iro;
				ex_print_ban[wk_te->ichi] = j;
			}else{
			/* 盤外へ書き込む必要あり　*/
				strcat( wstr, _itoa( j, wstr2, 10));
				strcat( wstr, "( " );
				if(ex_print_ban[wk_te->ichi] == 0){
					x = wk_te->ichi % (bansize + 1);
					y = wk_te->ichi / (bansize + 1);
					h_ichi = henkan_disp_in( x, y );
					x = h_ichi % (bansize + 1);
					strcat( wstr, my_itozenkaku(x));
					strcat( wstr, "の");
					y = h_ichi / (bansize + 1);
					strcat( wstr, my_itowazenkaku(y));
				}else{
					strcat( wstr, _itoa( ex_print_ban[wk_te->ichi], wstr2, 10));
				}
				strcat( wstr, ")  " );
			}
			j++;
		}
		
		if(wk_te->next == head){
			i++; /*通常の場合は最終手にプラス1されるのでそれにあわす */
			break;
		}

		wk_te=wk_te->next;
	}

	i--;
	if(print_start()==0){
		if(print_bangai( wstr, start_te, i /* 最後の手 */)==0){
			if(print_te(print_ban,ex_print_ban)==0){
				print_exec();
				Debugprint("kifu_print end!\n");
				return 0;
			}
		}
	}

	return -1;

}

int kifu_chg_put()
{
int i;
TE *wk_te;
TE *tmp_head;

	tmp_head = cell_get();
	if(tmp_head == NULL){
		return 1;
	}

	tmp_head->iro   = current_te->iro;
	tmp_head->ichi  = HEAD;
	for(i=0;i<bansize2;i++){
		tmp_head->ban[i] = ban[i];
	}
	for(wk_te = current_te->next;wk_te->brother !=wk_te;
		wk_te = wk_te->brother->next){
		;
	}
	wk_te->brother    = tmp_head;
	tmp_head->brother = wk_te;
	tmp_head->prev    = tmp_head;
	tmp_head->next    = tmp_head;
	tmp_head->black_capture_number = current_te->black_capture_number;
	tmp_head->white_capture_number = current_te->white_capture_number;
	
	current_te   = tmp_head;
	
	return 0;
}

int kifu_chg_cancel()
{
int i;
TE *wk_te;

	if(current_te != current_te->next || current_te == head){
		for(current_te=current_te->prev;current_te->ichi!=HEAD;current_te=current_te->prev){
			;
		}

		do{
			if(current_te->brother!=current_te){
				for(wk_te=current_te;wk_te->brother!=current_te;wk_te=wk_te->brother){
					;
				}
				current_te = wk_te;
			}
			current_te = current_te->prev;
		}while(current_te->iro==DELETE);
	
		for(i=0;i<bansize2;i++){
			ban[i] = current_te->ban[i];
		}

		return 0;
	}

	for(wk_te=current_te;wk_te->brother!=current_te;wk_te=wk_te->brother){
		;
	}
	wk_te->brother = current_te->brother;
	cell_free(current_te);

	for(current_te=wk_te->prev;current_te->iro==DELETE;current_te=current_te->prev){
		;
	}

	for(i=0;i<bansize2;i++){
		ban[i] = current_te->ban[i];
	}

	return 0;
}

int kifu_rebirth( int repeat_flag, int change_flag, int comment_flag )
{

	repeat_flg = repeat_flag;
	change_flg = change_flag;
	comment_flg = comment_flag;
	return 0;
}

/* 関数の作り方に問題あるかも知れないが取り合えず必要な物を作る */
int kifu_chg_flg_set( int change_flag)
{
int w_flg;

	w_flg = change_flg;
	change_flg = change_flag;
	return w_flg;
}

/* 関数の作り方に問題あるかも知れないが取り合えず必要な物を作る */
int kifu_rebirth_speed_set( int rebirth_speed)
{
int w_speed;

	w_speed = save_rebirth_speed;
	save_rebirth_speed = rebirth_speed;
	return w_speed;
}

int kifu_commentset(char *text)
{
int comment_no;

	comment_no = comment_set(text);
	current_te->comment = (short int)comment_no;
	return 0;
}

char *kifu_commentread()
{
	
	return comment_read((int)current_te->comment);

}

int kifu_captureread(int *black_capture_number, int *white_capture_number)
{

	*black_capture_number = current_te->black_capture_number;
	*white_capture_number = current_te->white_capture_number;
	return 0;

}

