void APTouchManager::touchEnded(cocos2d::Touch* touch, bool isCancelled) {
	auto id = touch->getID();
	// if not began
	if (id > 5)
		return;

	// they can be nullptr.
	auto originNode = _touchToBeganNode[id];
	auto nowNode = getTouchedNode(touch);

	if(isCancelled) {
		runHook(originNode, APTouchType::Cancelled, touch);

	}
	// if presently touching node differs with origin node
	else if (nowNode != originNode) {
		runHook(originNode, APTouchType::EndedOut, touch);
		runHook(nowNode, APTouchType::EndedInIgnoreBegan, touch);

	} else {
		runHook(originNode, APTouchType::EndedIn, touch);

	}

	_touchToBeganNode[id] = nullptr;
	_touchToNowNode[id] = nullptr;


	/*
	if (_touchIDMap.find(touch->getID()) != _touchIDMap.end()) {
		_touchIDMap.erase(touch->getID());
	} else {
		//cocos2d::log("weird touchEnded");
	}*/
}
int CreatureManager::Create(std::string avatar, int scriptRef) {
	//implicitly create the new object
	elementMap.emplace( std::pair<int, CreatureData>(counter, CreatureData(avatar, scriptRef)) );

	runHook(lua, createRef, &elementMap.find(counter)->second, counter);

	//TODO: do various things like saving to the database
	return counter++;
}
void CreatureManager::UnloadIf(std::function<bool(std::pair<const int, CreatureData const&>)> fn) {
	std::map<int, CreatureData>::iterator it = elementMap.begin();
	while (it != elementMap.end()) {
		if (fn(*it)) {
			runHook(lua, unloadRef, &it->second, it->first);
			it = elementMap.erase(it);
		}
		else {
			++it;
		}
	}
}
bool APTouchManager::onTouchBegan(cocos2d::Touch* touch, cocos2d::Event* event){

	//if touch count is over 6
	//if(touch->getID() > 5) return true;
/*
	if (_touchIDMap.find(touch->getID()) == _touchIDMap.end()) {
		_touchIDMap.insert(decltype(_touchIDMap)::value_type(touch->getID, nullptr));
	} else {
		//cocos2d::log("weird touchStarted");
	}
*/
	if(_amp == nullptr) {
		_amp = apHookActionManager::getInstance();
	}

	auto nowNode = getTouchedNode(touch);

	_touchToBeganNode[touch->getID()] = nowNode;
	_touchToNowNode[touch->getID()] = nowNode;


	runHook(nowNode, APTouchType::Began, touch);/*
	if (nowNode && !isBehaviorNullptr(nowNode, APTouchType::Began)) {
		_behaviorMap[APTouchType::Began][nowNode](touch);
	}*/

	return true;
/*
	for(const auto& item :_checkerMap) {
		if(item.second(touch) && _globalZOrderVec.at(item.first) > biggest) {
			node = item.first;
			biggest = _globalZOrderVec.at(item.first);
		}
	}
	if (node) {
		_behaviorMap.at(node)();
	}
*/
}
void APTouchManager::onTouchMoved(cocos2d::Touch* touch, cocos2d::Event* event){

	debug_d();
	auto id = touch->getID();

	if(id > 5) return;

	if(_amp == nullptr) {
		_amp = apHookActionManager::getInstance();
	}
	// if not began
	//if (_touchToBeganNode[id] == nullptr || id > 5)

	// they can be nullptr.
	auto nowNode = getTouchedNode(touch);
	auto beforeNode = _touchToNowNode[id];
	_touchToNowNode[id] = nowNode;

	//cocos2d::log("yo");

	auto originNode = _touchToBeganNode[id];
	// outside
	//auto& originNodeHook = _d[originNode].hook;
	//auto& nowNodeHook = _d[nowNode].hook;

	// originNode : node when began that touch.
	// nowNode: now touching node.
	// beforeNode: last touched node.

	// go in or go out. now touching node differs with the last touched one.

	////cocos2d::log("nowNode:%d, beforeNode:%d, originNode:%d", nowNode, beforeNode, originNode);

	if(beforeNode != nowNode) {
		//cocos2d::log("yo2");
		// drag to origin node
		if(nowNode == originNode) {
			runHook(nowNode, APTouchType::MovedInner, touch);
			runHook(beforeNode, APTouchType::MovedOuterIgnoreBegan, touch);
		}

		// if dragged not to origin node and the last node was origin Node
		else if(beforeNode == originNode) {
			runHook(nowNode, APTouchType::MovedInnerIgnoreBegan, touch);
			runHook(beforeNode, APTouchType::MovedOuter, touch);
		}

		// all different!
		else {
			runHook(nowNode, APTouchType::MovedInnerIgnoreBegan, touch);
			runHook(beforeNode, APTouchType::MovedOuterIgnoreBegan, touch);
		}
	}

	// before node and now node are same.
	else {
		//cocos2d::log("yo3");
		// if all same.
		if(nowNode == originNode) {
			runHook(nowNode, APTouchType::MovedInside, touch);
		}
		// if only origin node differs.
		else {
			runHook(nowNode, APTouchType::MovedInsideIgnoreBegan, touch);
			runHook(originNode, APTouchType::MovedOutside, touch);
		}

	}
	//cocos2d::log("yo4");




/*




	if (beforeNode != originNode && nowNode != originNode
			&& originNodeHook.find(APTouchType::MovedOutside) != originNodeHook.end()) {

		if(nowNode )
		_amp->runHook(originNodeHook[APTouchType::MovedOutside]);
	}
	// inside
	else if (beforeNode == originNode && nowNode == originNode
			&& originNodeHook.find(APTouchType::MovedInside) != originNodeHook.end()) {
		_amp->runHook(originNodeHook[APTouchType::MovedInside]);
	}

	// go to out
	else if (beforeNode == originNode && nowNode != originNode
			&& originNodeHook.find(APTouchType::MovedOuter) != originNodeHook.end()) {
		_amp->runHook(originNodeHook[APTouchType::MovedOuter]);

	}

	// inner
	else if (beforeNode != originNode && nowNode == originNode
			&& originNodeHook.find(APTouchType::MovedInner) != originNodeHook.end()) {
		_amp->runHook(originNodeHook[APTouchType::MovedInner]);
	}
*/

}
void CreatureManager::UnloadAll() {
	for (std::map<int, CreatureData>::iterator it = elementMap.begin(); it != elementMap.end(); it++) {
		runHook(lua, unloadRef, &it->second, it->first);
	}
	elementMap.clear();
}
void CreatureManager::Unload(int uid) {
	runHook(lua, unloadRef, &elementMap.find(uid)->second, uid);
	elementMap.erase(uid);
}