//---------------------- CalculateWeightedSum ----------------------------
//
//  this simply sums up all the active behaviors X their weights and 
//  truncates the result to the max available steering force before 
//  returning
//------------------------------------------------------------------------
Vector2D SteeringBehavior::CalculateWeightedSum(float dt)
{        
	//reset the steering force
	m_vSteeringForce.Zero();

	if (On(bounds_avoidance))
	{
		Vector2D force = BoundsAvoidance() * m_dWeightBoundsAvoidance;

		/*if (!force.isZero()) {
			std::cout << "avoid wall: " << force << std::endl;
		}*/

		m_vSteeringForce += force;
	}

	if (On(obstacle_avoidance))
	{
		Vector2D force = ObstacleAvoidance() * m_dWeightObstacleAvoidance;

		/*if (!force.isZero()) {
			std::cout << "avoid obst: " << force << std::endl;
		}*/

		m_vSteeringForce += force;
	}


	if (On(flee))
	{
		assert(fleeTarget && "Flee target not assigned");
		m_vSteeringForce += Flee(fleeTarget->Pos()) * m_dWeightFlee;
	}



	if (On(seek))
	{
		assert(seekTarget && "Seek target not assigned");
		m_vSteeringForce += Seek(seekTarget->Pos()) * m_dWeightSeek;
	}


	if (On(arrive))
	{
		assert(seekTarget && "Arrive target not assigned");
		m_vSteeringForce += Arrive(seekTarget->Pos(), m_Deceleration) * m_dWeightArrive;
	}


	if (On(wander))
	{

		Vector2D force = Wander(dt) * m_dWeightWander;

		//std::cout << "wander: " << force << std::endl;

		m_vSteeringForce += force;
	}



	if (On(pursuit))
	{
		assert(pursuitTarget && "pursuit target not assigned");

		m_vSteeringForce += Pursuit(pursuitTarget) * m_dWeightPursuit;
	}

	if (On(offset_pursuit))
	{
		assert (pursuitTarget && "pursuit target not assigned");

		m_vSteeringForce += OffsetPursuit(pursuitTarget, m_vOffset) * m_dWeightOffsetPursuit;
	}

	if (On(hide))
	{
		assert(hideTarget && "Hide target not assigned");

		m_vSteeringForce += Hide() * m_dWeightHide;
	}


	if (On(forward)) {
		Vector2D force = Forward() * m_dWeightForward;

		m_vSteeringForce += force;
	}

	//m_vSteeringForce.Truncate(m_pMovingEntity->MaxForce());
	return m_vSteeringForce;
}
Vec2 SteeringForce::Calculate()
{
    
    m_vSteeringForce  = Vec2::ZERO;
    Vec2 force;
    
    std::vector<Vehicle*> neighbors;
    
    if (On(allignment)||On(separation)||On(cohesion)) {
        
        if (m_pVehicle->isCellSpaceOn()) {
            
            CellSpacePartition<Vehicle*>* cellSpace = GameData::Instance()->getCellSpace();
            neighbors = cellSpace->getNeighbors();
            
        }else{
        auto data = GameData::Instance()->getEntityVector();
        
        neighbors = tagNeighbors(m_pVehicle,data,SearchRad);
        }
    }
    
    if (On(wall_avoidance)) {
        auto data = GameData::Instance()->getWallls();
        force = WallAvoidance(data);
        
        if (!AccumulateForce(m_vSteeringForce, force)) {
            return  m_vSteeringForce;
        }
    }
    
    if (On(obstacle_avoidance)) {
        
        auto data = GameData::Instance()->getObstacle();
        force = ObstacleAvoidance(data);
        
        if (!AccumulateForce(m_vSteeringForce, force)) {
            return  m_vSteeringForce;
        }
    }
    
    
    
    if (On(separation)) {
        
        force = Separation(neighbors);
        if (!AccumulateForce(m_vSteeringForce, force)) {
            return  m_vSteeringForce;
        }
    }
    
    if (On(cohesion)) {
        
        force = Cohesion(neighbors);
        if (!AccumulateForce(m_vSteeringForce, force)) {
            return  m_vSteeringForce;
        }
    }
    
    if (On(allignment)) {
        
        force = Alignment(neighbors);
        if (!AccumulateForce(m_vSteeringForce, force)) {
            return  m_vSteeringForce;
        }
    }
    
    
    
    if (On(hide)) {
        CCASSERT(m_pVehicle->getHideTarget()!=nullptr, "不存在躲避目标");
        auto data = GameData::Instance()->getEntityVector();
        force = Hide(m_pVehicle->getHideTarget(),data);
        if (!AccumulateForce(m_vSteeringForce, force)) {
            return  m_vSteeringForce;
        }
    }
    
    if (On(follow_path)) {
        force = PathFollow();
        
        if (!AccumulateForce(m_vSteeringForce, force)) {
            return  m_vSteeringForce;
        }
    }
    if (On(seek)) {
        
        force = Seek(m_pVehicle->getTarget());
        
        if (!AccumulateForce(m_vSteeringForce, force)) {
            return  m_vSteeringForce;
        }
        
    }
    
    if (On(flee)) {
        force = Flee(m_pVehicle->getTarget());
        if (!AccumulateForce(m_vSteeringForce, force)) {
            return  m_vSteeringForce;
        }
    }
    
    if (On(arrive)) {
        force = Arrive(m_pVehicle->getTarget(), fast);
        if (!AccumulateForce(m_vSteeringForce, force)) {
            return  m_vSteeringForce;
        }
    }
    
    if (On(offset_pursuit)) {
        force = OffsetPursuit(m_pVehicle->getLeader(), m_pVehicle->getOffsetToLeader());
        if (!AccumulateForce(m_vSteeringForce, force)) {
            return  m_vSteeringForce;
        }
    }
    
    if (On(pursuit)) {
        force = Pursuit(m_pVehicle->getEvaderv());
        if (!AccumulateForce(m_vSteeringForce, force)) {
            return  m_vSteeringForce;
        }
    }
    if (On(evade)) {
        force = Evade(m_pVehicle->getPursuer());
        if (!AccumulateForce(m_vSteeringForce, force)) {
            return  m_vSteeringForce;
        }
    }
    
    if (On(wander)) {
        force = Wander();
        if (!AccumulateForce(m_vSteeringForce, force)) {
            return  m_vSteeringForce;
        }
    }
    
    if (On(interpose)) {
        force = Interpose(m_pVehicle->getInterposeA(), m_pVehicle->getInterposeB());
        if (!AccumulateForce(m_vSteeringForce, force)) {
            return  m_vSteeringForce;
        }
    }
    
    return m_vSteeringForce;
}
//---------------------- CalculatePrioritized ----------------------------
//
//  this method calls each active steering behavior in order of priority
//  and acumulates their forces until the max steering force magnitude
//  is reached, at which time the function returns the steering force 
//  accumulated to that  point
//------------------------------------------------------------------------
Vector2D SteeringBehavior::CalculatePrioritized(float dt)
{
	//reset the steering force
	m_vSteeringForce.Zero();

	Vector2D force;

	if (On(bounds_avoidance))
	{
		force = BoundsAvoidance() * m_dWeightBoundsAvoidance;

		if (!AccumulateForce(m_vSteeringForce, force)) return m_vSteeringForce;
	}

	if (On(obstacle_avoidance))
	{
		force = ObstacleAvoidance() * m_dWeightObstacleAvoidance;

		if (!AccumulateForce(m_vSteeringForce, force)) return m_vSteeringForce;
	}

	if (On(flee))
	{
		assert(fleeTarget && "Flee target not assigned");
		force = Flee(fleeTarget->Pos()) * m_dWeightFlee;

		if (!AccumulateForce(m_vSteeringForce, force)) return m_vSteeringForce;
	}

	if (On(seek))
	{
		assert(seekTarget && "Seek target not assigned");
		force = Seek(seekTarget->Pos()) * m_dWeightSeek;

		if (!AccumulateForce(m_vSteeringForce, force)) return m_vSteeringForce;
	}


	if (On(arrive))
	{
		assert(seekTarget && "Arrive target not assigned");
		force = Arrive(seekTarget->Pos(), m_Deceleration) * m_dWeightArrive;

		if (!AccumulateForce(m_vSteeringForce, force)) return m_vSteeringForce;
	}

	if (On(wander))
	{
		force = Wander(dt) * m_dWeightWander;

		if (!AccumulateForce(m_vSteeringForce, force)) return m_vSteeringForce;
	}

	if (On(pursuit))
	{
		assert(pursuitTarget && "pursuit target not assigned");

		force = Pursuit(pursuitTarget) * m_dWeightPursuit;

		if (!AccumulateForce(m_vSteeringForce, force)) return m_vSteeringForce;
	}

	if (On(offset_pursuit))
	{
		assert (pursuitTarget && "pursuit target not assigned");

		force = OffsetPursuit(pursuitTarget, m_vOffset);

		if (!AccumulateForce(m_vSteeringForce, force)) return m_vSteeringForce;
	}

	if (On(hide))
	{
		assert(hideTarget && "Hide target not assigned");

		force = Hide() * m_dWeightHide;

		if (!AccumulateForce(m_vSteeringForce, force)) return m_vSteeringForce;
	}

	if (On(forward)) {
		force = Forward() * m_dWeightForward;

		if (!AccumulateForce(m_vSteeringForce, force)) return m_vSteeringForce;
	}

	return m_vSteeringForce;
}