/*---------------------------------------------------------------------
	簡易記法変換エンジン「あやりりす/EX」
	
	記法（頭の識別1文字はカスタム可能）
	
	エ０２：ほげほげ～
	テ１２：（ほげほげ｜ふがふが｜ふにゃふにゃ）～
	テ消　：どこいった～！
	二人　：バルス！
	エ０３「こんな書き方もできるよ」
	
	待ち無しエ０５： //\w3　「待無」でも可
	待ちゼロエ０６： //まったくなし　「待０」でも可
	待ち多めエ０８： //\w9 x 4　「待多」でも可
	改行無しエ０２： //改行しない
	クリック待ちエ０４： //\x
	改行前エ０３： //改行・ウエイト前に表情を変える
	
	（ユーザ）さん！
	
	＃これはコメントです
	
	＠設定：パッシブモード
	＠設定：クイックセクション
	＠設定：タイムアウト1000「時間切れ」 //<-単位ミリ秒、時間切れ、を呼出
	
	//｜区切り、1つめは表示文字列、以降はイベント名とその追加情報
	//イベント名＝関数名とできる場合がある
	//  ・あやりりす環境のすべて、OnChoiceSelectにEVALで細工、Onではじまる文字列
	＠メニュー：さんぷる１｜Sample1Execute
	＠半分メニュー：さんぷる２｜さんぷる２実行
	＠改行多めメニュー：さんぷる３｜OnTest3Exec｜R0
	＠クリック待ちメニュー：さんぷる４｜さんぷる4実行 //この直後でクリック待ち(\x)実行
	
	すべて
	<<"
	エ０２：てすと！
	">>
	のように囲むこと（AYA複数行記法）
	
	ランダムトークのみ
	<<'
	テ１０：てすとだね。
	'>>
	のようになります。(高速化のため)
	
	補助関数 (通常は細工不要)
	あやりりすEXSurfaceTranslate(？側,サーフィス番号)
	 -> 返りサーフィス番号
	あやりりすEXSakuraScript外部トランスレータ(スクリプト)
	 -> 返り変換後スクリプト
	
---------------------------------------------------------------------*/

//---- あやりりすEX初期化 --------------------------------------------------------------
OnSystemLoad.AAA_AYLEX
{
	timeout_label = ''
	entering_passive_mode = 0
	
	AYALilithEX = 1
	
	_a = GETFUNCLIST('あやりりすEXヘッダ')
	
	AYLex_CHAR_HEADER = IARRAY
	AYLex_CHAR_REGEX = ''
	
	AYLex_Kakko_History = IARRAY
	
	_n = ARRAYSIZE(_a)
	for _i = 0 ; _i < _n ; _i++ {
		_side = TOINT(ZEN2HAN(REPLACE(_a[_i],'あやりりすEXヘッダ','')))
		_var = EVAL(_a[_i])
		
		AYLex_CHAR_HEADER[_side] = _var
		if _i > 0 {
			AYLex_CHAR_REGEX += '|'
		}
		AYLex_CHAR_REGEX += _var
	}
	
	AYLex_DEFAULT_SURFACE = (0,10)
	
	_a = GETFUNCLIST('あやりりすEX標準表情')
	
	_n = ARRAYSIZE(_a)
	for _i = 0 ; _i < _n ; _i++ {
		_side = TOINT(ZEN2HAN(REPLACE(_a[_i],'あやりりすEX標準表情','')))
		_var = TOINT(EVAL(_a[_i]))
		
		AYLex_DEFAULT_SURFACE[_side] = _var
	}
	
	
	AYLex_SakuraScript_Wait_Insert = 0
	if ISFUNC('あやりりすEXSakuraScript文ウエイト支援') {
		AYLex_SakuraScript_Wait_Insert = あやりりすEXSakuraScript文ウエイト支援
	}
	
	AYLex_SakuraScript_External_Translator = ISFUNC('あやりりすEXSakuraScript外部トランスレータ')
}

//---- あやりりすEXデータ開放 --------------------------------------------------------------
OnSystemUnload.AAA_AYLEX
{
	ERASEVAR('AYLex_CHAR_HEADER','AYLex_CHAR_REGEX','AYLex_SakuraScript_Wait_Insert','AYLex_Kakko_History','AYLex_SakuraScript_External_Translator')
	
	ERASEVAR('timeout_label','entering_passive_mode','AYALilithEX')
}

//---- あやりりすEXトランスレータ --------------------------------------------------------------
OnTranslateInternal.AAA_AYLEX
{
	if SUBSTR(SHIORI3FW.Eventid,0,3) == 'On_' {
		_argv[0]
		return
	}
	ProcessSpecialSyntax(_argv[0])
}

//---- テキストのみフィルタ --------------------------------------------------------------
AYALilithEX.TextOnlyTranslator
{
	_string = RE_SPLIT(_argv[0],'\\(\\|q\[.*?\]\[.*?\]|[!&8cfijmpqsn]\[.*?\]|[-*+014567bcehntuvxz]|_[ablmsuvw]\[.*?\]|__(t|[qw]\[.*?\])|_[!?+nqsV]|[sipw][0-9])')
	_n = ARRAYSIZE(_string)
	_tag = RE_GETSTR()
	_tr = ''
	_qs = 0
	
	for _i = 0 ; _i < _n ; _i++ {
		_tr += EVAL("%(_argv[1])(_string[_i],_qs)")
		_tr += _tag[_i]
		if '\_q' _in_ _tag[_i] {
			_qs = ! _qs
		}
	}
	
	_tr
}

//---- テキスト変換部（句読点ウエイト） --------------------------------------------------------------
AYALilithEX.TextOnlyTranslatorFunc
{
	//_argv[0] = 置換対象テキスト
	//_argv[1] = クイックセクション内か否か
	
	_text = _argv[0]
	
	_text = REPLACE(_text,'‥','…')
	_text = RE_REPLACE(_text,'[（(](ユーザー*|ユーザー*名|ユーザー*さん)[)）]',username)
	
	if ! _argv[1] {
		_text = RE_REPLACEEX(_text, '([、…])(?=.)', '$1\\w5')
		_text = RE_REPLACEEX(_text, '([。！？」』])(?=[^。、！？」』])', '$1\\w9')
	}
	_text
}

//---- チェイン・選択 --------------------------------------------------------------
ProcessSpecialSyntax
{
	_txt = _argv[0]
	
	_arr = RE_SPLIT(_txt,'\r\n[=＝]{4,}\r\n',2) //=====区切りでchain
	if STRLEN(_arr[1]) {
		SHIORI3FW.StartChainTalkScriptDirect(_arr[1])
	}
	
	_txt = _arr[0]
	
	_arr = RE_SPLIT(_txt,'\r\n[-―ー－]{4,}\r\n') //-----区切りで複数トークRAND選択

	if GETTYPE(_arr) == 4 {
		_txt = _arr[RAND(ARRAYSIZE(_arr))]
	}
	else {
		_txt = _arr
	}
	
	ProcessAYALilithSyntax(_txt)
}

//---- あやりりすEX記法サブ（カッコで囲まれた補助記法） --------------------------------------------------------------
ProcessAYALilithSyntaxSub
{
	_text = _argv[0]
	if TOINT(_argv[1]) == 0 {
		_text = AYALilithEX.TextOnlyTranslator(_text,'AYALilithEX.TextOnlyTranslatorFunc')
	}
	
	while RE_SEARCH(_text,'[(（](.+?[\|｜].+?|[HＨ][0-9０-９]+)[)）]') {
		_p = RE_GETPOS[0]
		_l = RE_GETLEN[0]
		_s = RE_GETSTR[1]
		
		_x = ZEN2HAN(_s)

		_text = ERASE(_text,_p,_l)

		_hist = ''
		if SUBSTR(_x,0,1) == 'H' { //履歴
			_histnum = TOINT(SUBSTR(_x,1,9999))
			_hist = AYLex_Kakko_History[_histnum-1]
		}
		else {
			_hist = ANY(RE_SPLIT(_s,'[|｜]'));
		}
		_text = INSERT(_text,_p,_hist)
		AYLex_Kakko_History ,= _hist
	}
	
	_text
}

//---- あやりりすEX記法メイン --------------------------------------------------------------
ProcessAYALilithSyntax
{
	timeout_label = ''
	AYLex_Kakko_History = IARRAY
	
	_txtarray  = IARRAY
	_txtarray ,= SPLIT(_argv[0],CHR(0xd,0xa))
	
	_script = ''
	
	_surface_translate_name = 'あやりりすEXSurfaceTranslate'
	_surface_translate_found = ISFUNC(_surface_translate_name)
	
	if (ARRAYSIZE(_txtarray) <= 1) && (RE_SEARCH(_txtarray[0],'^[^\\]*(' + AYLex_CHAR_REGEX + ')[^\\]*?[｢「：]') == 0) {
		_script = _txtarray[0]
		if AYLex_SakuraScript_Wait_Insert {
			_script = ProcessAYALilithSyntaxSub(_script,0)
		}
		else {
			_script = ProcessAYALilithSyntaxSub(_script,1)
		}
		if AYLex_SakuraScript_External_Translator {
			void EVAL('_script = あやりりすEXSakuraScript外部トランスレータ(_script)')
		}
		_script
		return
	}

	_init_script = ''
	_talk_init = 0
	_talk_init_side = IARRAY
	_talk_done_side = IARRAY
	_side = 0
	_side_old = 0
	_sync = 0
	_is_exit = 0
	_quick = 0
	_passive_set = 0
	_timeout_value = 0
	_kagikakko_flag = 0
	_cond_result = 0
	_last_cond_result = 0
	_else_cond_result = 0
	
	_menu_flag = 0
	_half_menu_flag = 0
	
	_n = ARRAYSIZE(_txtarray)
	for _i = 0 ; _i < _n ; _i++ {
		_txt = _txtarray[_i]
		if _txt != '' {
			_txt_exit = RE_REPLACE(_txt,'(\\w[1-9])*\\-','')
			if _txt != _txt_exit {
				_is_exit = 1
				_txt = _txt_exit
			}

			if RE_SEARCH(_txt,'^[#＃]') { //＃コメント
				; //なにもしない
			}
			elseif RE_SEARCH(_txt,'^(.*?)([＜].+?)$') {
				_cmd_orig = RE_GETSTR[1]
				_txt_orig = RE_GETSTR[2]
				
				if RE_SEARCH(_txt_orig,'^[：＜](.+)$') {
					_txt_orig = RE_GETSTR[1]
					_kagikakko_flag = 0
				}
				elseif RE_SEARCH(_txt_orig,'^[｢「](.+?)[」｣]$') {
					_txt_orig = RE_GETSTR[1]
					_kagikakko_flag = 0
				}
				elseif RE_SEARCH(_txt_orig,'^[｢「](.+?)$') {
					_txt_orig = RE_GETSTR[1]
					_kagikakko_flag = 1
				}
				
				_cmd_orig = RE_REPLACE(_cmd_orig,'【.+?】','')
				_cond = RE_GETSTR[0]
				
				_cmd_orig = RE_REPLACE(_cmd_orig,'[　 \t]','')
				
				if STRLEN(_cond) > 0 {
					if RE_SEARCH(_cond,'^【[　 \t]*直前.*?否定[　 \t]*?】$') {
						_cond_result = (_last_cond_result == 0)
					}
					elseif RE_SEARCH(_cond,'^【[　 \t]*直前.*?[　 \t]*?】$') {
						_cond_result = _last_cond_result
					}
					elseif RE_SEARCH(_cond,'^【[　 \t]*(?:それ以外|else)[　 \t]*?】$') {
						_cond_result = (_else_cond_result == 0)
					}
					else {
						_last_cond_result = ProcessAYALilithCondBranch(_cond)
						_cond_result = _last_cond_result
						
						if _last_cond_result {
							_else_cond_result = 1
						}
					}
				}
				else {
					_cond_result = 1
					_else_cond_result = 0
				}
				
				//条件分岐ONならGO (からっぽの場合含む)
				if _cond_result {
					if RE_SEARCH(_cmd_orig,'^[@＠](.*?)メニュー') { //＠メニュー：ほげほげ
						_cmd = RE_REPLACE(RE_GETSTR[1],'[　 \t]','')
						_txt = _txt_orig
						
						if _menu_flag == 0 {
							if _quick == 0 {
								_script += '\_q'
							}
							_script += '\_n'
							if TOINT(_talk_done_side[_side]) != 0 {
								_script += '\n[half]' //\nは後で入る
							}
						}
						
						_menu_array = RE_SPLIT(_txt,'[|｜]')
						
						if '半分' _in_ _cmd {
							if _half_menu_flag == 0 {
								_script += 半分メニュー開始()
								_half_menu_flag = 1
								_script += '\n'
							}
							_script += 半分メニュー(_menu_array)
						}
						else {
							if _half_menu_flag {
								_script += 半分メニュー終了()
								_half_menu_flag = 0
							}
							else {
								if (TOINT(_talk_done_side[_side]) != 0) || (_menu_flag != 0) {
									_script += '\n'
								}
							}
							if '改行多め' _in_ _cmd || '改行多目' _in_ _cmd || '改多' _in_ _cmd {
								_script += '\n[half]'
							}
							_script += メニュー(_menu_array)
							if 'クリック待ち' _in_ _cmd {
								_talk_done_side = IARRAY
								_talk_init = 0
								_script += '\0\x'
								_side = 0
								_side_old = 0
							}
						}
						_talk_done_side[_side] = 1
						_menu_flag = 1
					}
					elseif RE_SEARCH(_cmd_orig,'^[#＃@＠]設定') { //＠設定：ほげほげ
						_txt = RE_REPLACE(_txt_orig,'[　 \t]','')
						
						if 'クイック' _in_ _txt {
							if _quick == 0 {
								_quick = 1
								_script += '\_q'
							}
							else {
								_quick = 0
								_script += '\_q'
							}
						}
						else {
							if _quick != 0 {
								_quick = 0
								_script += '\_q'
							}
						}
						
						if '受動モード' _in_ _txt || 'パッシブモード' _in_ _txt {
							_passive_set = 1
							if entering_passive_mode == 0 {
								_script += '\![enter,passivemode]'
								entering_passive_mode = 1
							}
						}
						
						if 'タイムクリ' _in_ _txt {
							_script += '\t'
						}
						
						if RE_MATCH(_txt,'タイムアウト([0-9０-９]*)[｢「：](.+?)[」｣]?') {
							timeout_label = RE_GETSTR[2]
							if RE_GETSTR[1] != '' {
								_timeout_value = TOINT(ZEN2HAN(RE_GETSTR[1]))
							}
						}
					}
					else {
						if _half_menu_flag {
							_script += 半分メニュー終了()
							_half_menu_flag = 0
						}
						if _menu_flag {
							if _quick == 0 {
								_script += '\_q'
							}
							_script += '\_n'
							_menu_flag = 0
						}
						
						_main = _txt_orig
						_cmd = _cmd_orig
						
						_cmd_wait = _cmd
						_cmd = REPLACE(_cmd,'待ち無し','')
						_cmd = REPLACE(_cmd,'待ちなし','')
						_cmd = REPLACE(_cmd,'待無','')
						_cmd_wait = (_cmd != _cmd_wait)
						
						_cmd_waitzero = _cmd
						_cmd = REPLACE(_cmd,'待ちゼロ','')
						_cmd = REPLACE(_cmd,'待０','')
						_cmd_waitzero = (_cmd != _cmd_waitzero)

						_cmd_morewait = _cmd
						_cmd = REPLACE(_cmd,'待ち多め','')
						_cmd = REPLACE(_cmd,'待ち多目','')
						_cmd = REPLACE(_cmd,'待多','')
						_cmd_morewait = (_cmd != _cmd_morewait)
						
						_cmd_line = _cmd
						_cmd = REPLACE(_cmd,'改行無し','')
						_cmd = REPLACE(_cmd,'改行なし','')
						_cmd = REPLACE(_cmd,'改無','')
						_cmd_line = (_cmd != _cmd_line)
						
						_cmd_moreline = _cmd
						_cmd = REPLACE(_cmd,'改行多め','')
						_cmd = REPLACE(_cmd,'改行多目','')
						_cmd = REPLACE(_cmd,'改多','')
						_cmd_moreline = (_cmd != _cmd_moreline)
						
						_cmd_click = _cmd
						_cmd = REPLACE(_cmd,'クリック待ち','')
						_cmd_click = (_cmd != _cmd_click)
						
						_cmd_before = _cmd
						_cmd = REPLACE(_cmd,'改行前','')
						_cmd_before = (_cmd != _cmd_before)
						
						_side_change = ''
						_side_wait = ''
						_side_wait_short = ''
						
						if _talk_init != 0 {
							if _cmd_click {
								_talk_done_side = IARRAY
								_talk_init = 0
								_side_wait += '\0\x'
								_side = 0
								_side_old = 0
							}
							elseif _quick == 0 {
								if _cmd_waitzero {
									; //NOOP
								}
								elseif _cmd_wait { //待ち無し
									_side_wait += "\w3"
									_side_wait_short += "\w2"
								}
								elseif _cmd_morewait { //待ち多め
									_side_wait += "\w9\w9\w9\w9"
									_side_wait_short += "\w9\w9"
								}
								else { //待ち普通
									_side_wait += "\w9\w9"
									_side_wait_short += "\w9"
								}
							}
						}
						
						_surface_defined_flag = 0
						while 1 {
							_pattern_found = 0
							
							_patnum = ARRAYSIZE(AYLex_CHAR_HEADER)
							for _pat = 0 ; _pat < _patnum ; _pat++ {
								if STRLEN(AYLex_CHAR_HEADER[_pat]) {
									if RE_SEARCH(_cmd,'^' + AYLex_CHAR_HEADER[_pat] + '([0-9.,０-９．，消bｂバ]*)') {
										_pattern_found = 1
										_side = _pat
										if _sync {
											_sync = 0
											_side_change += '\_s'
											_talk_done_side[0] = 1
											_talk_done_side[1] = 1
										}
										_cmd = ERASE(_cmd,0,RE_GETLEN[0])
										if _side < 2 {
											_side_change += "\%(_side)"
										}
										else {
											_side_change += "\p[%(_side)]"
										}
										
										_spat = RE_GETSTR[1]
										if _spat != '' {
											_talk_init_side[_side] = 1
											
											_spat_a = RE_SPLIT(_spat,'[.．,，bｂバ]',3)
											_spat_s = RE_GETSTR()
											
											if '消' _in_ _spat_a[0] {
												_side_change += "\s[-1]"
											}
											elseif _spat_a[0] != '' {
												_surface = TOINT(ZEN2HAN(_spat_a[0]))
												if _surface_translate_found {
													_surface_x = EVAL("%(_surface_translate_name)(_side,_surface)")
													if STRLEN(TOSTR(_surface_x)) {
														_surface = _surface_x
													}
												}
												_side_change += "\s[%(_surface)]"
											}
											
											for _k = 1 ; _k < 3 ; _k++ {
												if _spat_a[_k] != '' {
													if RE_MATCH(_spat_s[_k-1],'[bｂバ]') {
														if '消' _in_ _spat_a[_k] {
															_side_change += "\b[-1]"
														}
														elseif _spat_a[_k] != '' {
															_side_change += "\b[%(TOINT(ZEN2HAN(_spat_a[_k])))]"
														}
													}
													else {
														if _spat_a[_k] != '' {
															_side_change += "\i[%(TOINT(ZEN2HAN(_spat_a[_k])))]"
														}
													}
												}
											}
											
											_surface_defined_flag = 1
										}
									}
								}
							}
							
							if _pattern_found {
								//NOOP - ループ内実行済み
							}
							elseif SUBSTR(_cmd,0,2) == '二人' {
								_cmd = ERASE(_cmd,0,2)
								if _sync == 0 {
									_sync = 1
									_side_change += '\_s'
								}
							}
							else {
								break
							}
						}
						
						_side_changed_flag = _side_old != _side
						if TOINT(_talk_done_side[_side]) != 0 {
							if _cmd_line == 0 {
								if _side_changed_flag {
									if _cmd_moreline {
										_side_change += "\n\n"
									}
									else {
										_side_change += "\n\n[half]"
									}
								}
								else {
									if _cmd_moreline {
										_side_change += "\n\n[half]"
									}
									else {
										_side_change += "\n"
									}
								}
							}
						}
						_side_old = _side
						
						if _talk_init == 0 {
							if TOINT(_talk_init_side[0]) == 0 {
								_init_script = "\0\s[%(AYLex_DEFAULT_SURFACE[0])]"
							}
							elseif TOINT(_talk_init_side[1]) == 0 {
								_init_script = "\1\s[%(AYLex_DEFAULT_SURFACE[1])]\0"
							}
						}
						
						if (_surface_defined_flag == 0) && (_side_changed_flag == 0) {
							_side_wait = _side_wait_short
						}
						
						if _cmd_before {
							_script += _side_change
							_script += _side_wait
						}
						else {
							_script += _side_wait
							_script += _side_change
						}
						
						_talk = ProcessAYALilithSyntaxSub(_main,_quick)
						if _talk != '' {
							_talk_done_side[_side] = 1
							_script += _talk
						}
						_talk_init = 1
					}
				}
			}
			else {
				_else_cond_result = 0
				
				if _quick == 0 {
					_script += "\w9"
				}
				if _kagikakko_flag {
					if RE_SEARCH(_txt,'^(.+?)[」｣]$') {
						_txt = RE_GETSTR[1]
						_kagikakko_flag = 0
					}
				}
				_script += "\n";
				_script += ProcessAYALilithSyntaxSub(_txt,_quick)
			}
			
			if entering_passive_mode != 0 {
				if _passive_set == 0 {
					_script += '\![leave,passivemode]'
					entering_passive_mode = 0
				}
			}
			
		}
	}

	if _is_exit {
		_script += "\w9\-";
	}
	
	if _timeout_value {
		_script = "\![set,balloontimeout,%(_timeout_value)]\![set,choicetimeout,%(_timeout_value)]" + _script
	}
	//これが必ず最後
	if _init_script != '' {
		_script = _init_script + _script
	}
	_script
}

//---- 条件分岐 --------------------------------------------------------------
ProcessAYALilithCondBranch
{
	_t = _argv[0]
	_t = RE_REPLACE(_t,'[【】]','')
	
	if STRLEN(_t) == 0 {
		1
		return
	}
	
	_t = ReplaceAbbrevSyntax(_t,'[RＲ]','reference')
	_t = ReplaceAbbrevSyntax(_t,'[AＡ]','_argv')

	TOINT(EVAL(_t)) != 0
}

ReplaceAbbrevSyntax
{
	_ta = RE_SPLIT(_argv[0],_argv[1] + '[0-9０-９]+')
	_tr = RE_GETSTR()
	
	_n = ARRAYSIZE(_ta)
	_t = _ta[0]
	
	_res = ''
	for _i = 1 ; _i < _n ; _i++ {
		_res = _tr[_i-1]
		_res = RE_REPLACE(_res,_argv[1],'')
		
		_res = _argv[2] + '[' + TOINT(ZEN2HAN(_res)) + ']'
		
		_t += _res
		
		_t += _ta[_i]
	}
	_t
}

//---- テスト用イベント --------------------------------------------------------------
OnTextDrop
{
	REPLACE(reference.raw[0],CHR(1),CHR(0xd,0xa))
}

//---- メニュー系 --------------------------------------------------------------

//エスケープ
エスケープ
{
	_r = _argv[0]
	if RE_SEARCH(_r,'["\[\]]') {
		'"' + REPLACE(_r,'"','""') + '"'
	}
	else {
		_r
	}
}

//通常メニュー
メニュー
{
	'\![*]\q['
	--
	エスケープ( SHIORI3FW.MakeJustText(_argv[0],46) )
	--
	_n = ARRAYSIZE(_argv)
	_s = ''
	for _i = 1 ; _i < _n ; _i++ {
		_s += ',' + エスケープ(_argv[_i])
	}
	_s
	--
	']'
}

//半分メニュー
半分メニュー開始
{
	half_menu_counter = 0
}
半分メニュー初期化
{
	half_menu_counter = 0
}

半分メニュー終了
{
	if 半分メニュー無効 {
		''
		return
	}
	if half_menu_counter != 0 {
		'\n'
	}
}
半分メニュー
{
	if 半分メニュー無効 {
		メニュー(_argv) + '\n'
		return
	}
	
	if (half_menu_counter % 2) == 0 {
		if half_menu_counter != 0 {
			'\n'
		}
	}
	--
	'\![*]\q['
	--
	エスケープ( SHIORI3FW.MakeJustText(_argv[0],21) )
	--
	_n = ARRAYSIZE(_argv)
	_s = ''
	for _i = 1 ; _i < _n ; _i++ {
		_s += ',' + エスケープ(_argv[_i])
	}
	_s
	--
	']'
	--
	if (half_menu_counter % 2) == 0 {
		'\_l[145]'
	}
	half_menu_counter++
}
