local TS = require(
	game:GetService("ReplicatedStorage")
		:WaitForChild("RobloxTS")
		:WaitForChild("Include")
		:WaitForChild("RuntimeLib")
);
local _exports = {};
local State;
do
	State = {
				init = function(self, characterController)
			warn("Default init method is being used on " .. self.id .. ".");
		end;
				start = function(self, characterController)
			warn("Default start method is being used on " .. self.id .. ".");
		end;
				stop = function(self, characterController)
			warn("Default stop method is being used on " .. self.id .. ".");
		end;
	};
	State.__index = {};
	State.new = function(...)
		return State.constructor(setmetatable({}, State), ...);
	end;
	State.constructor = function(self, ...)
		return self;
	end;
	State.id = "Default";
end;
local StateController;
do
	StateController = {};
	StateController.__index = {
		addState = function(self, state)
			state:init(self.characterController);
			self.states[state.id] = state;
		end;
		addStates = function(self, states)
			TS.array_forEach(states, function(state)
				self:addState(state);
			end);
		end;
		setState = function(self, stateName)
			local state = self.states[stateName];
			if state then
				local previousState = self.stateObject;
				if previousState then
					previousState:stop(self.characterController);
				end;
				self.stateObject = state;
				state:start(self.characterController);
			else
				error(stateName .. " is not a valid state.");
			end;
		end;
		getState = function(self)
			return self.stateObject.id;
		end;
	};
	StateController.new = function(...)
		return StateController.constructor(setmetatable({}, StateController), ...);
	end;
	StateController.constructor = function(self, characterController)
		self.characterController = characterController;
		self.states = {};
		self.stateObject = State;
		return self;
	end;
end;
_exports.State = State;
_exports.StateController = StateController;
return _exports;
