#include "agent.h"
#include "environment.h"
#include <iostream>
#include <iomanip>
using namespace std;

// -----------------------------------------------------------
Agent::ActionType Agent::Think()
{
	//建地圖 
	if(stage == 1)
	{ 
		//若碰牆 則退回上一點 
		if(bump_)
		{
			MAP[x][y] = 'W';
			if(status == "UP") x = x+1;
			else if(status == "DOWN") x = x-1;
			else if(status == "RIGHT") y = y-1;
			else if(status == "LEFT") y = y+1;
			record("BACK");			
			if (dirty_) return actSUCK;
			else return actIDLE;
		}
		if (dirty_) return actSUCK;
	
		//上面沒走過 
		if(MAP[x-1][y] == '-')
		{
			status = Up();
			record("UP");
		}
		//左邊沒走過 
		else if(MAP[x][y-1] == '-')
		{
			status = Left();
			record("LEFT");
		}
		//右邊沒走過
		else if(MAP[x][y+1] == '-')
		{
			status = Right();
			record("RIGHT");	
		}
		//下面沒走過 
		else if(MAP[x+1][y] == '-')
		{
			status = Down();
			record("DOWN");
		}
		//都走過
		else                                                          
		{
			//DFS 退回上一點 與ACT所記錄的方向相反 
			if(ACT[now-1] == 'U')
			{
				stageACT[stageNow] = 'D';
				status = Down();				
			}
			else if(ACT[now-1] == 'D')
			{
				stageACT[stageNow] = 'U';
				status = Up();
			}
			else if(ACT[now-1] == 'L')
			{
				stageACT[stageNow] = 'R';
				status = Right();
			}
			else if(ACT[now-1] == 'R')
			{
				stageACT[stageNow] = 'L';
				status = Left();
			}
			//若建完地圖 則進入stage2開始巡迴整張地圖 
			else if(ACT[now-1] == 'I')
			{	
				stage = 2;	
				if (dirty_) return actSUCK;
				else return actIDLE;
			}
			record("gogoBACK");
		}
	}
	
// -----------------------------------------------------------
// -----------------------------------------------------------

	//巡迴地圖 
	else if(stage == 2)
	{	
		if (dirty_) return actSUCK;
		count++;
		//若已經走完整張地圖 則再次巡迴 
		if(count == stageNow) count = 0;
		if(stageACT[count] == 'U') return actUP;
		else if(stageACT[count] == 'D') return actDOWN;
		else if(stageACT[count] == 'L') return actLEFT;
		else if(stageACT[count] == 'R') return actRIGHT;
		else if(stageACT[count] == 'I')
		{
			if (dirty_) return actSUCK;
			return actIDLE;
		}
	}	
	
	if(status == "UP") return actUP;
	else if(status == "DOWN") return actDOWN;
	else if(status == "RIGHT") return actRIGHT;
	else if(status == "LEFT") return actLEFT;
	else if(status == "IDLE")
	{
		if (dirty_) return actSUCK;
		return actIDLE;
	}
}
// -----------------------------------------------------------
string Agent::Up()
{
	if(MAP[x][y] == '-')
		MAP[x][y] = 'R';
	x = x-1;
	return "UP";
}
// -----------------------------------------------------------
string Agent::Down()
{
	if(MAP[x][y] == '-')
		MAP[x][y] = 'R';
	x = x+1;
	return "DOWN";
}
// -----------------------------------------------------------
string Agent::Left()
{
	if(MAP[x][y] == '-')
		MAP[x][y] = 'R';
	y = y-1;
	return "LEFT";
}
// -----------------------------------------------------------
string Agent::Right()
{
	if(MAP[x][y] == '-')
		MAP[x][y] = 'R';
	y = y+1;
	return "RIGHT";
}
// -----------------------------------------------------------
void Agent::record(string temp)
{
	if(temp == "BACK")
	{
		now -= 1;
		pos -= 2;
		stageNow--;
		return;
	}
	//因為stageACT需要記錄回去的路 所以stageNow++ 
	if(temp == "gogoBACK")
	{
		now -= 1;
		pos -= 2;
		stageNow++;
		return;
	}
	
	if(temp == "UP")
	{
		ACT[now] = 'U';
		stageACT[stageNow] = 'U';
	}
	else if(temp == "DOWN")
	{
		ACT[now] = 'D';
		stageACT[stageNow] = 'D';
	}
	else if(temp == "LEFT")
	{
		ACT[now] = 'L';
		stageACT[stageNow] = 'L';
	}
	else if(temp == "RIGHT")
	{
		ACT[now] = 'R';
		stageACT[stageNow] = 'R';
	}
	
	position[pos] = x;
	position[pos+1] = y;
	
	now += 1;
	pos += 2;
	stageNow += 1;
	
}
// -----------------------------------------------------------
void Agent::Perceive(const Environment &env)
{
	bump_ = env.isJustBump();
	dirty_ = env.isCurrentPosDirty();
}
// -----------------------------------------------------------
string ActionStr(Agent::ActionType action)
{
	switch (action)
	{
	case Agent::actUP: return "UP";
	case Agent::actDOWN: return "DOWN";
	case Agent::actLEFT: return "LEFT";
	case Agent::actRIGHT: return "RIGHT";
	case Agent::actSUCK: return "SUCK";
	case Agent::actIDLE: return "IDLE";
	default: return "???";
	}
}
// -----------------------------------------------------------
