----------------------------------------------------------------------------------------------------------
-- 
----------------------------------------------------------------------------------------------------------
ActionPlayer=extends(NamedObject);

	----------------------------------------------------------------------------------------------------------
	-- 
	----------------------------------------------------------------------------------------------------------
	function ActionPlayer:constructor()
		self.name = "ActionPlayer";

		-- 実行関数登録 一部を除き、フレーム進めるのは使う側。
		self.playingMethods = {};
		self.playingMethods[1] = self.phase_keyReset;
		self.playingMethods[2] = self.phase_waitAfterMotion;
		self.playingMethods[3] = self.phase_inputCommand;
		self.playingMethods[4] = self.phase_waitChangeNewAction;
		self.playingMethods[5] = self.phase_afterChangeNewAction;
		self.playingMethods[6] = self.phase_frameWait;
		--self.playingMethods[7] = self.phase_terminate;

		self:reset();
	end

	----------------------------------------------------------------------------------------------------------
	-- 
	----------------------------------------------------------------------------------------------------------
	function ActionPlayer:reset()
		self.playing = false;
		self.playingCaptureInfo = nil;
		self.playingMotion = nil;
		self.waitFrame = 0;
		self.waitChangeActionFrame = 0;
		self.phase = 1;
		self.elapsFrame = 0;
		key_reset();
	end

	----------------------------------------------------------------------------------------------------------
	-- 
	----------------------------------------------------------------------------------------------------------
	function ActionPlayer:initialize(captureInfo)
		if (captureInfo == nil)
		then
			logger:trace(self.name, "選択行動なし");
			yield(); -- 強制的に進める。
			return;
		end

		if (self.playingCaptureInfo ~= nil)
		then
			logger:warn(self.name, "なぜかはいってきた");
			yield(); -- 強制的に進める。
			return;
		end

		self.playing = true;
		self.playingCaptureInfo = captureInfo;
	
		-- すでに同一行動とって連打してる状態を回避
		-- 例えば遠A打ってる最中に、また遠A使用とするケース。
		if (captureInfo.act == getTargetCurrentAction(TARGET_MY))
		then
			logger:debug(self.name, "同じ行動連打しようとしてるので何もしない。 my_act : " .. getTargetCurrentAction(TARGET_MY));
			self:reset();
			yield(); -- 強制的に進める。
			return;
		end
		--[[
		]]--

		-- 行動値に対するMotionインスタンス取得
		self.playingMotion = motionMapping:get(captureInfo.act);

		-- 対応するMotionインスタンスがなければ何もしない。
		if (self.playingMotion == nil)
		then
			logger:warn(self.name, "対応するモーションMappingなし : " .. self.playingCaptureInfo.act);
			self:reset();
			yield(); -- 強制的に進める。
			return;
		end

		logger:info(self.name, "play() 行動開始 : " .. self.playingMotion.name);

		-- カード実行の場合準備がちゃんと出来てるか確認。 評価関数でもやってるけど一応。
		if (isCardUseMotion(self.playingCaptureInfo.act) and 
			(not ((my_card == self.playingCaptureInfo:getParameter(CaptureInfo_my_card)) and is_card_use)))
		then
			logger:warn(self.name, "カード利用準備できてない。 : " .. self.playingCaptureInfo.act .. 
									" captureInfo.my_card:" .. self.playingCaptureInfo:getParameter(CaptureInfo_my_card) ..
									" my_card:" .. my_card ..
									" is_card_use:" .. tostring(is_card_use));
			self:reset();
			yield(); -- 強制的に進める。
			return;
		end
	end

PHASE_STATUS_COMPLETED=0;
PHASE_STATUS_COMPLETED_YIELD=1;
PHASE_STATUS_RUNNING=2;
PHASE_STATUS_BREAK=3;

KEY_EVENT_WAIT=2;
	----------------------------------------------------------------------------------------------------------
	-- 
	----------------------------------------------------------------------------------------------------------
	function ActionPlayer:forward()
		local playMethod = self.playingMethods[self.phase];
		if (playMethod == nil)
		then
			logger:warn(self.name, "再生するメソ\ッドがありません。phase:" .. self.phase);
			return
		end

		local status = playMethod(self);
		-- 実行中
		if (status == PHASE_STATUS_RUNNING)
		then
			logger:trace(self.name, "Player実行中:" .. self.playingCaptureInfo.act ..
									" phase:" .. self.phase ..
									" status:" .. status ..  
									" playing:" .. tostring(self.playing) .. 
									" キー入力:" .. getKetStatString());
			self.elapsFrame = self.elapsFrame + 1;
			yield();
			return;
		-- Phaseが終わった場合 yield()なし
		elseif (status == PHASE_STATUS_COMPLETED)
		then
			logger:debug(self.name, "PlayerPhase完了:" .. self.playingCaptureInfo.act ..
									" phase:" .. self.phase ..
									" status:" .. status ..  
									" playing:" .. tostring(self.playing) .. 
									" キー入力:" .. getKetStatString());

			if (#self.playingMethods == self.phase)
			then
				self:reset();
				return;
			end

			self.elapsFrame = self.elapsFrame + 1;
			self.phase = self.phase + 1;
			return;
		-- Phaseが終わった場合 yield()あり
		elseif (status == PHASE_STATUS_COMPLETED_YIELD)
		then
			logger:debug(self.name, "PlayerPhase完了Yield:" .. self.playingCaptureInfo.act ..
									" phase:" .. self.phase .. 
									" status:" .. status ..  
									" playing:" .. tostring(self.playing) .. 
									" キー入力:" .. getKetStatString());

			if (#self.playingMethods == self.phase)
			then
				self:reset();
				return;
			end

			self.elapsFrame = self.elapsFrame + 1;
			self.phase = self.phase + 1;
			yield();
			return;
		-- 何らかの原因で中断
		else
			-- PHASE_STATUS_BREAK時
			logger:debug(self.name, "Player中断:" .. self.playingCaptureInfo.act ..
									" phase:" .. self.phase .. 
									" status:" .. tostring(status) ..  
									" playing:" .. tostring(self.playing) .. 
									" キー入力:" .. getKetStatString());
			self:reset();
			return;
		end
	end

	----------------------------------------------------------------------------------------------------------
	-- 
	----------------------------------------------------------------------------------------------------------
	function ActionPlayer:phase_keyReset()
		-- 行動再生前にキーリセットね。
		--key_reset();
		return PHASE_STATUS_COMPLETED;
	end

	----------------------------------------------------------------------------------------------------------
	-- 
	----------------------------------------------------------------------------------------------------------
	function ActionPlayer:phase_waitAfterMotion()
		-- from 161_common_functions.lua isAfterMotion()
		if (isAfterMotion(getTargetCurrentAction(TARGET_MY)))
		then
			logger:debug(self.name, "経過モーション待ち中 : " .. getTargetCurrentAction(TARGET_MY) ..
									" captureInfo.act:" .. self.playingCaptureInfo.act);
			--wait(1);
			return PHASE_STATUS_RUNNING;
		else
			return PHASE_STATUS_COMPLETED;
		end
	end

	----------------------------------------------------------------------------------------------------------
	-- 
	----------------------------------------------------------------------------------------------------------
	function ActionPlayer:phase_inputCommand()
		-- motion_mapping で定義されたボタン押し
		self.playingMotion:action();
		logger:debug(self.name, "★ボタン押され状況:" .. getKetStatString() ..
								" 押した時間:" .. battle_time);
		wait(KEY_EVENT_WAIT); -- 安定のため。
		return PHASE_STATUS_COMPLETED;
		--return PHASE_STATUS_COMPLETED_YIELD; -- yield()しないと安定しない。
	end

	----------------------------------------------------------------------------------------------------------
	-- 
	----------------------------------------------------------------------------------------------------------
	function ActionPlayer:phase_waitChangeNewAction()
		-- ボタン押し結果が反映されたらこのフェーズは完了
		if (tracer[TARGET_MY]:current().act == self.playingCaptureInfo.act)
		then
			logger:debug(self.name, "行動が変化した。" ..
						" phase_waitChangeNewAction() 行動名:" .. self.playingMotion.name  .. 
						" waitChangeActionFrame:" .. self.waitChangeActionFrame .. 
						" my_frame: " .. my_frame .. 
						" cap.frame:" .. self.playingCaptureInfo.frame .. 
						" 待ったframe:" .. self.waitChangeActionFrame .. 
						" my_act:" .. my_act .. 
						" 変わったと判断した時間:" .. battle_time ..
						" cap.motion:" .. self.playingCaptureInfo.act );
			return PHASE_STATUS_COMPLETED;
		end

		-- ボタン押しが反映されるまで待つ。
		if (self.waitChangeActionFrame <= WAIT_CHANGE_ACTION_LIMIT)
		then
			self.waitChangeActionFrame = self.waitChangeActionFrame + 1;
			return PHASE_STATUS_RUNNING;
		else
			logger:warn(self.name, "★限界まで待っても行動が変化しない。" ..
						" phase_waitChangeNewAction() 行動名:" .. self.playingMotion.name  .. 
						" waitChangeActionFrame:" .. self.waitChangeActionFrame .. 
						" my_frame: " .. my_frame .. 
						" cap.frame:" .. self.playingCaptureInfo.frame .. 
						" 待ったframe:" .. self.waitChangeActionFrame .. 
						" my_act:" .. my_act .. 
						" 変わらないと判断した時間:" .. battle_time ..
						" cap.motion:" .. self.playingCaptureInfo.act );
			return PHASE_STATUS_BREAK;
		end
		error("phase_waitChangeNewAction");
	end

	----------------------------------------------------------------------------------------------------------
	-- 
	----------------------------------------------------------------------------------------------------------
	function ActionPlayer:phase_afterChangeNewAction()
		-- 意味を成さないので没
		--self.waitFrame = self.waitFrame - KEY_EVENT_WAIT; -- KeyEventで待った分引く。
		--[[
		if (self.playingMotion:isWaitCutMyFrame())
		then 
			self.waitFrame = self.waitFrame - my_frame; 
			logger:debug(self.name, "waitCutMyFrame 行動名 : " .. self.playingMotion.name .. " waitFrame : " .. self.waitFrame .. " my_frame : " .. my_frame);
		end
		]]--

		-- キーリセット
		if (not self.playingMotion:isDisableKeyReset())
		then
			logger:debug(self.name, "key_reset() after action() 行動名 : " .. self.playingMotion.name .. " waitFrame : " .. self.waitFrame .. " my_frame : " .. my_frame);
			key_reset();
		end
		return PHASE_STATUS_COMPLETED;
	end

	----------------------------------------------------------------------------------------------------------
	-- 
	----------------------------------------------------------------------------------------------------------
	function ActionPlayer:phase_frameWait()
		-- 持続行動の場合、行動フレーム数分待ち
		if (not self.playingMotion:isDisableWait()) 
		then
			-- AAAAコンボ先行入力対応
			local waitFrame = self.playingCaptureInfo.frame;
			if (isAComboMotion(tracer[TARGET_MY]:current().act))
			then
				waitFrame = waitFrame - 15; -- 強制先行入力
			end
			--[[
			]]--

			-- tracerと付け合せてるのでカット不要。
			if (tracer[TARGET_MY]:current().frame < waitFrame) 
			then
				return PHASE_STATUS_RUNNING;
			elseif (isIncrementAirMotion(tracer[TARGET_MY]:current().act) and (y > 0) and (my_xspeed < 0) and (y < 20)) -- TODO 恣意的な着地硬直回避
			then
				logger:debug(self.name, " 恣意的完了frame wait() 行動名 : " .. self.playingMotion.name .. 
										" current.frame : " .. tracer[TARGET_MY]:current().frame .. 
										" cap.frame:" .. self.playingCaptureInfo.frame .. 
										" 待ち完了と判断した時間:" .. battle_time ..
										" my_frame : " .. my_frame);
				return PHASE_STATUS_COMPLETED;
			else
				logger:debug(self.name, "frame wait() 行動名 : " .. self.playingMotion.name .. 
										" current.frame : " .. tracer[TARGET_MY]:current().frame .. 
										" cap.frame:" .. self.playingCaptureInfo.frame .. 
										" 待ち完了と判断した時間:" .. battle_time ..
										" my_frame : " .. my_frame);
				return PHASE_STATUS_COMPLETED;
			end
		else
			logger:debug(self.name, " 行動待ちなし完了 frame wait() 行動名 : " .. self.playingMotion.name .. 
									" current.frame : " .. tracer[TARGET_MY]:current().frame .. 
									" cap.frame:" .. self.playingCaptureInfo.frame .. 
									" 待ち完了と判断した時間:" .. battle_time ..
									" my_frame : " .. my_frame);
			return PHASE_STATUS_COMPLETED;
		end
	end

	----------------------------------------------------------------------------------------------------------
	-- 
	----------------------------------------------------------------------------------------------------------
	function ActionPlayer:phase_terminate()
		self:reset();
		return PHASE_STATUS_COMPLETED;
	end
