// --------------------------------------------------------
// --------------------------------------------------------
void SMAHeat::Init(World & parWorld)
{
	CellularAutomata const & celluls = parWorld.GetCelluls();
	PointI const & mapSize = celluls.GetSize();

	int nbCluster = mapSize.x * mapSize.y / 100;

	for (int i = 0; i < nbCluster; ++i)
	{
		int minPosX = (i % (mapSize.x / 10)) * 10;
		int minPosY = (i / (mapSize.x  / 10)) * 10;
		ReachabilityCluster * cluster = new ReachabilityCluster(minPosX, minPosX + 10, minPosY, minPosY + 10);
		FReachabilityClusters.push_back(cluster);
	}
	FDecisionalAgent.push_back(new DecisionalAgent(this));
}
// --------------------------------------------------------
// --------------------------------------------------------
void SMAHeat::BuildVisionCache(World const & parWorld, Agent* parAgent)
{
	std::cout << "build Cluster internal link <=> Agent" << std::endl;
	ReachabilityCluster * cluster = NULL;
	for (auto const & currentCluster : FReachabilityClusters)
	{
		if (currentCluster->Contains(parAgent))
			cluster = currentCluster;
	}

	ReachablePathFind pathFind(&parWorld.GetCelluls(), cluster);
	// Reachabilite entre les different agent et les lien interieur
	for (auto& link : cluster->GetLinks())
    {
        Position p1 = { link->x, link->y };
        Position p2 = { parAgent->X(), parAgent->Y() };
        pathFind.Init(p1, p2);
        unsigned int dist = pathFind.ComputePath();
        if (dist)
        {
            link->ReachableAgents.push_back(AgentWithDist(parAgent, dist));
        }
    }
}
// --------------------------------------------------------
// --------------------------------------------------------
void SMAHeat::BuildVisionCache(World const & parWorld)
{
	std::cout << "Vuild Vision cache" << std::endl;
	CellularAutomata const & celluls = parWorld.GetCelluls();
	PointI const & mapSize = celluls.GetSize();

	std::cout << "build Cluster external link" << std::endl;
	for (unsigned int i = 0; i < FReachabilityClusters.size(); ++i)
	{
		ReachabilityCluster * currentCluster = FReachabilityClusters[i];
		// bot
		{
			unsigned int otherClusterIndex = i + 0 + 1 * mapSize.x / CLUSTER_SIZE;
			if (otherClusterIndex < FReachabilityClusters.size())
			{
				ReachabilityCluster * oCluster = FReachabilityClusters[otherClusterIndex];
				if (currentCluster->MaxX() >= mapSize.x) continue;
				CreateLinkBot(celluls, currentCluster, oCluster, currentCluster->MinX(), 
					currentCluster->MinX() + CLUSTER_SIZE, currentCluster->MaxY());
			}
		}

		// right
		{
			unsigned int otherClusterIndex = i + 1 + 0 * mapSize.x / CLUSTER_SIZE;
			if (otherClusterIndex < FReachabilityClusters.size())
			{
				ReachabilityCluster * oCluster = FReachabilityClusters[otherClusterIndex];
				if (currentCluster->MaxX() >= mapSize.x) continue;
				CreateLinkRight(celluls, currentCluster, oCluster, currentCluster->MinY(), 
					currentCluster->MinY() + CLUSTER_SIZE, currentCluster->MaxX());
			}
		}
	}

	std::cout << "build Cluster internal link <=> link" << std::endl;

	for (ReachabilityCluster * cluster : FReachabilityClusters)
	{
		ReachablePathFind pathFind(&celluls, cluster);
		// Reachabilite entre les different lien vers l'exterieur
		for (auto& link : cluster->GetLinks())
        {
            for (auto const & oLink : cluster->GetLinks())
            {
                if (link == oLink)
                    continue;
                Position p1 = { link->x, link->y };
                Position p2 = { oLink->x, oLink->y };
                pathFind.Init(p1, p2);
                unsigned int dist = pathFind.ComputePath();
                if (dist)
                {
                    link->ReachableLinks.push_back(LinkWithDist(oLink, dist));
                }
            }
        }
	}
	std::cout << "build Cluster: End" << std::endl;
	std::vector<Link const *> links;
	for (ReachabilityCluster * cluster : FReachabilityClusters)
		for (auto& link : cluster->GetLinks())
			links.push_back(link);
	FLinkPathFinder.Init(links, mapSize.x, mapSize.y);
}