// This is the Ex-'GameStateManager::SingleThreadEntryPoint(void*)' function
void* SingleThreadEntryPoint(void *iPointer)
{
	EventLoop* loop = static_cast<EventLoop*>(iPointer);
	
	GameHandle siHandle = BFG::generateHandle();

	gViewComposerState.reset(new ViewComposerState(siHandle, loop));
	gComposerState.reset(new ComposerState(siHandle, loop));

	// Init Controller
	GameHandle handle = generateHandle();

	{
		BFG::Controller_::ActionMapT actions;
		actions[A_QUIT] = "A_QUIT";
		actions[A_LOADING_MESH] = "A_LOADING_MESH";
		actions[A_LOADING_MATERIAL] = "A_LOADING_MATERIAL";
		actions[A_CAMERA_AXIS_X] = "A_CAMERA_AXIS_X";
		actions[A_CAMERA_AXIS_Y] = "A_CAMERA_AXIS_Y";
		actions[A_CAMERA_AXIS_Z] = "A_CAMERA_AXIS_Z";
		actions[A_CAMERA_MOVE] = "A_CAMERA_MOVE";
		actions[A_CAMERA_RESET] = "A_CAMERA_RESET";
		actions[A_CAMERA_ORBIT] = "A_CAMERA_ORBIT";
		actions[A_SCREENSHOT] = "A_SCREENSHOT";
		actions[A_LOADING_SKY] = "A_LOADING_SKY";

		actions[A_CREATE_LIGHT] = "A_CREATE_LIGHT";
		actions[A_DESTROY_LIGHT] = "A_DESTROY_LIGHT";
		actions[A_PREV_LIGHT] = "A_PREV_LIGHT";
		actions[A_NEXT_LIGHT] = "A_NEXT_LIGHT";
		actions[A_FIRST_LIGHT] = "A_FIRST_LIGHT";
		actions[A_LAST_LIGHT] = "A_LAST_LIGHT";

		actions[A_INFO_WINDOW] = "A_INFO_WINDOW";

		actions[A_CAMERA_MOUSE_X] = "A_CAMERA_MOUSE_X";
		actions[A_CAMERA_MOUSE_Y] = "A_CAMERA_MOUSE_Y";
		actions[A_CAMERA_MOUSE_Z] = "A_CAMERA_MOUSE_Z";
		actions[A_CAMERA_MOUSE_MOVE] = "A_CAMERA_MOUSE_MOVE";

		actions[A_SUB_MESH] = "A_SUB_MESH";
		actions[A_TEX_UNIT] = "A_TEX_UNIT";
		actions[A_ANIMATION] = "A_ANIMATION";
		actions[A_ADAPTER] = "A_ADAPTER";

		actions[A_UPDATE_FEATURES] = "A_UPDATE_FEATURES";

		BFG::Controller_::fillWithDefaultActions(actions);	
		BFG::Controller_::sendActionsToController(loop, actions);

		Path path;
		const std::string config_path = path.Expand("Composer.xml");
		const std::string state_name = "Composer";
		
		BFG::View::WindowAttributes wa;
		BFG::View::queryWindowAttributes(wa);
		
		Controller_::StateInsertion si(config_path, state_name, handle, true, wa);

		EventFactory::Create<Controller_::ControlEvent>
		(
			loop,
			ID::CE_LOAD_STATE,
			si
		);

		loop->connect(A_QUIT, gComposerState.get(), &ComposerState::ControllerEventHandler);
		loop->connect(A_SCREENSHOT, gComposerState.get(), &ComposerState::ControllerEventHandler);

		loop->connect(A_LOADING_MESH, gViewComposerState.get(), &ViewComposerState::controllerEventHandler);
		loop->connect(A_LOADING_MATERIAL, gViewComposerState.get(), &ViewComposerState::controllerEventHandler);
		loop->connect(A_CAMERA_AXIS_X, gViewComposerState.get(), &ViewComposerState::controllerEventHandler);
		loop->connect(A_CAMERA_AXIS_Y, gViewComposerState.get(), &ViewComposerState::controllerEventHandler);
		loop->connect(A_CAMERA_AXIS_Z, gViewComposerState.get(), &ViewComposerState::controllerEventHandler);
		loop->connect(A_CAMERA_MOVE, gViewComposerState.get(), &ViewComposerState::controllerEventHandler);
		loop->connect(A_CAMERA_RESET, gViewComposerState.get(), &ViewComposerState::controllerEventHandler);
		loop->connect(A_CAMERA_ORBIT, gViewComposerState.get(), &ViewComposerState::controllerEventHandler);
		loop->connect(A_LOADING_SKY, gViewComposerState.get(), &ViewComposerState::controllerEventHandler);

		loop->connect(A_CREATE_LIGHT, gViewComposerState.get(), &ViewComposerState::controllerEventHandler);
		loop->connect(A_DESTROY_LIGHT, gViewComposerState.get(), &ViewComposerState::controllerEventHandler);
		loop->connect(A_PREV_LIGHT, gViewComposerState.get(), &ViewComposerState::controllerEventHandler);
		loop->connect(A_NEXT_LIGHT, gViewComposerState.get(), &ViewComposerState::controllerEventHandler);
		loop->connect(A_FIRST_LIGHT, gViewComposerState.get(), &ViewComposerState::controllerEventHandler);
		loop->connect(A_LAST_LIGHT, gViewComposerState.get(), &ViewComposerState::controllerEventHandler);

		loop->connect(A_INFO_WINDOW, gViewComposerState.get(), &ViewComposerState::controllerEventHandler);
		loop->connect(A_SUB_MESH, gViewComposerState.get(), &ViewComposerState::controllerEventHandler);
		loop->connect(A_TEX_UNIT, gViewComposerState.get(), &ViewComposerState::controllerEventHandler);
		loop->connect(A_ANIMATION, gViewComposerState.get(), &ViewComposerState::controllerEventHandler);
		loop->connect(A_ADAPTER, gViewComposerState.get(), &ViewComposerState::controllerEventHandler);

		loop->connect(A_CAMERA_MOUSE_X, gViewComposerState.get(), &ViewComposerState::controllerEventHandler);
		loop->connect(A_CAMERA_MOUSE_Y, gViewComposerState.get(), &ViewComposerState::controllerEventHandler);
		loop->connect(A_CAMERA_MOUSE_Z, gViewComposerState.get(), &ViewComposerState::controllerEventHandler);
		loop->connect(A_CAMERA_MOUSE_MOVE, gViewComposerState.get(), &ViewComposerState::controllerEventHandler);

		loop->connect(BFG::ID::A_MOUSE_MIDDLE_PRESSED, gViewComposerState.get(), &ViewComposerState::controllerEventHandler);
		loop->connect(BFG::ID::A_MOUSE_LEFT_PRESSED, gViewComposerState.get(), &ViewComposerState::controllerEventHandler);
		loop->connect(BFG::ID::A_MOUSE_RIGHT_PRESSED, gViewComposerState.get(), &ViewComposerState::controllerEventHandler);

		loop->connect(A_UPDATE_FEATURES, gViewComposerState.get(), &ViewComposerState::toolEventHandler);
	}
	return 0;
}