#####################################################################
# gmm_set_agb_msg.pl
# エクセルファイルのAGB版の翻訳をgmmにはりつけます。
#####################################################################
use strict;
use utf8;

require 'pm/util/log.pm';
require 'pm/util/file.pm';
require 'pm/xls/xls.pm';
require 'pm/gmm/gmm.pm';
require 'pm/gmm/row.pm';
require 'tbl.pm';

my $LANG_LIST =
{
	'USA'	=>	['英','EnglishMessage'],
	'FRA'	=>	['仏','FrenchMessage'],
	'NOE'	=>	['独','GermanMessage'],
	'ITA'	=>	['伊','ItalianMessage'],
	'SPA'	=>	['西','SpanishMessage']
};

&main();

# main
#####################################################################
sub main()
{
	# 引数
	my ($org_dir,$out_dir,$lang,$set,$xls_file,$sheet_list) = check_arg();

	my $agb_msg = getAgbMsg($xls_file,$sheet_list,$lang);

	# ディレクトリ以下のファイルのリストを取得します。
	my @file_list = ();
	util::file::getFileList( \@file_list,$org_dir );

	# 各ファイルに対して処理を行う
	foreach my $org_file (@file_list)
	{
		# ファイルが gmm でない場合は次へ
		next unless ($org_file =~ /^\Q$org_dir\E(.+\.gmm)$/);
		my $file_name = $1;
		util::log::setFileName($file_name);# ログ用

		# 出力ファイル名の設定
		my $out_file = $out_dir.$file_name;
		
		# ウインドウ情報をに設定する。
		my $gmm = gmm->new($org_file);
		setAgbMsg($gmm,$set,$agb_msg);

		# 変換した gmm をファイルに保存
		$gmm->print($out_file);
	}
}

####################################################################
# エクセルからAGBのメッセージを取得する。
####################################################################
sub getAgbMsg()
{
	my ($xls_file,$sheet_list,$lang) = @_; 
	
	# エクセルからのデータの読み込み
	my $xls = xls->new($xls_file);
	
	my %agb_msg_hash;
	foreach my $sheet_name (@$sheet_list)
	{
		util::log::setFileName("$xls_file:$sheet_name");	#ログ用			
		my $data_list = $xls->getData($sheet_name);

		my $title = shift(@$data_list);
		
		my $idx_id = getIdx($title,'id');
		my $idx_japanese = getIdx($title,'日');
		my $idx_agb_japanese = getIdx($title,'日(Emerald)');
		my $idx_agb_foreign = getIdx($title,$lang);

		foreach my $data (@$data_list)
		{
			my $id = $data->[$idx_id];
			util::log::setID($id);	#ログ用	
			my $msg_japanese		= getData($data,$idx_japanese);
			my $msg_agb_japanese	= getData($data,$idx_agb_japanese);
			my $msg_agb_foreign		= getData($data,$idx_agb_foreign);

			# AGB版のメッセージが埋められていない場合は無視。
			if ($msg_agb_foreign ne '')
			{
				my $msg_foreign			= correctMessage(
											$msg_japanese,
											$msg_agb_japanese,
											$msg_agb_foreign);
							
				$agb_msg_hash{$id} = $msg_foreign;
			}
		}
	}
	return \%agb_msg_hash;
}

# タイトル行から列のインデックスを取得する。
# 取得できなかった場合は-1を返す。
sub getIdx()
{
	my ($title,$val) = @_;

	my $i = 0;
	foreach my $data (@$title)
	{
		return $i if ($data eq $val);
		$i++;
	}

	return -1;
}
# 取得できなかった場合は""を返す。
sub getData()
{
	my ($data,$idx) = @_;
	return '' if ($idx < 0);
	return $data->[$idx];
}
#-------------------------------------------------------------------
# メッセージをチェックする。
#-------------------------------------------------------------------
sub correctMessage()
{
	my ($japanese,$agb_japanese,$agb_foreign) = @_;

	# '#XXX'の置換（'#var'を除く)
	my $foreign = replaceSharp($agb_foreign);

	my $tag_list_japanese 		= getTagList($japanese);
	my $var_list_agb_japanese	= getVarList($agb_japanese);
	my $var_list_foreign		= getVarList($foreign);	

	# '#var'の置換	
	if (@$var_list_foreign != 0)
	{
		# 日本語版に#varが含まれていない場合
		# もしくは日本語のAGB版の翻訳がシートにない場合
		if (@$var_list_agb_japanese == 0)
		{
			util::log::msg('error',$japanese,$foreign,'日本語にはない#varが含まれています。');
		}
		# 日本語版に#varが含まれている場合
		else
		{
			# #varの置換
			my $hash_var2tag = getVar2TagList($tag_list_japanese,$var_list_agb_japanese);
			$foreign = replaceVar($hash_var2tag,$foreign);
		}
	}

	# タグのチェック
	my $tag_list_foreign = getTagList($foreign);
	if ( checkTag($tag_list_japanese,$tag_list_foreign) != 0)
	{
		util::log::msg('warning',$japanese,$foreign,'日本語とタグセットが異なります。');
	}

	return $foreign;
}
#-------------------------------------------------------------------
# tag2varのリストを取得する
#-------------------------------------------------------------------
sub getVar2TagList()
{
	my ($list_tag,$list_var) = @_;

	# タグと#Varの対応テーブル作成
	my %hash;
	if (@$list_tag == @$list_var)
	{
		my $max = @$list_tag;
		for (my $i=0; $i<$max; $i++)
		{
			my $key = $list_var->[$i];
			my $val = '['.$list_tag->[$i].']';
			$hash{$key} = $val;
		}
	}
	return \%hash;
}
#-------------------------------------------------------------------
# 日本語のメッセージを参照して
#-------------------------------------------------------------------
sub replaceVar()
{
	my ($hash,$msg) = @_;
	
	while (my ($key,$val) = each(%$hash))
	{
		$msg =~ s/\Q$key\E/$val/g;
	}
	return $msg;
}
#-------------------------------------------------------------------
# タグをチェックする。
# 問題がある場合はログに出力する。
#-------------------------------------------------------------------
sub checkTag()
{
	my ($japanese_list,$foreign_list) = @_;

	# タグから名前を除く
	# 日本語と英語で比較できないので…
	my %japanese;
	foreach my $tag (@$japanese_list)
	{
		$tag =~ /^(.*?[^\\]:.*?[^\\]:)(.*?[^\\])(:.+)/;
		$japanese{"$1tagname$3"} = $2;
	}

	my %foreign;
	foreach my $tag (@$foreign_list)
	{
		$tag =~ /^(.*?[^\\]:.*?[^\\]:)(.*?[^\\])(:.+)/;
		$foreign{"$1tagname$3"} = $2;
	}

	foreach my $key (keys %japanese)
	{
		if (exists($foreign{$key}))
		{
			delete($japanese{$key});
			delete($foreign{$key});
		}
	}

	return keys(%japanese)+keys(%foreign);
}
#-------------------------------------------------------------------
# #XXXを適切な形に変換する。（#varを除く)
#-------------------------------------------------------------------
sub replaceSharp()
{
	my ($msg) = @_;

	while (my ($key,$val) = each(%{$TBL::SHARP}))
	{
		if ($msg =~ s/\Q$key\E/$val/g)
		{
			# ログ出力
			util::log::msg('replace',$key,'->',$val);
		}
	}
	return $msg;
}
#-------------------------------------------------------------------
# タグのリストへの参照を取得
#-------------------------------------------------------------------
sub getTagList()
{
	my ($msg) = @_;

	my @list;	# タグリスト

	# [*]にマッチするものを取得する。
	# \[,\]は無視する。
	# 先頭の[も認識させるために正規表現がみにくくなってしもた
	my $i = 0;
	while ($msg =~ /(^\[|[^\\]\[)(.+?[^\\])\]/)
	{
		$list[$i++]  = $2; #タグの値
		$msg = $';
	}

	return \@list;
}
#-------------------------------------------------------------------
# Varのリストへの参照を取得
#-------------------------------------------------------------------
sub getVarList()
{
	my ($msg) = @_;

	my @list;	# Varリスト

	my $i = 0;
	while ($msg =~ /(\#var\w)/)
	{
		$list[$i++]  = $1; #タグの値
		$msg = $';
	}

	return \@list;
}
####################################################################
# ＡＧＢのメッセージを反映させる。
####################################################################
sub setAgbMsg
{
	my ($gmm,$key,$agb_msg) = @_;

	while ( my ($id,$row) = each(%{$gmm->{'row'}}) )
	{
		util::log::setID($id);#ログ用

		if (defined($agb_msg->{$id}))
		{
			# garbage は無視
			if ($row->get('WindowContext') eq 'garbage')
			{
				# ログ出力
				util::log::msg('INFO','garbageなので無視しました');
				next;
			}
		
			my $msg = $agb_msg->{$id};
			$row->set($key,$msg);
		}
	}
}
#####################################################################
# 引数のチェック
#####################################################################
sub check_arg()
{
	if (@ARGV >= 4)
	{
		return
		(
			shift(@ARGV).'/',
			shift(@ARGV).'/',
			check_option(shift(@ARGV)),
			shift(@ARGV),			
			\@ARGV
		);
	}
	else
	{
		&help();
		exit;
	}
}
#-------------------------------------------------------------------
# 言語指定のチェック
#-------------------------------------------------------------------
sub check_option
{
	my ($opt) = @_;

	if (defined($LANG_LIST->{$opt}))
	{
		return @{$LANG_LIST->{$opt}};
	}
	
	print STDERR "error! illegal option:$opt\n";
	&help();
	exit;			
}
#-------------------------------------------------------------------
# ヘルプ表示
#-------------------------------------------------------------------
sub help()
{
	print STDERR "gmm_set_agb_msg.pl <base dir> <out dir> <lang> <xls> sheet1.. \n";
	print STDERR "lang\n";
	print STDERR "\tFRA\n";
	print STDERR "\tNOE\n";
	print STDERR "\tITA\n";
	print STDERR "\tSPA\n";
}
