double
FemtoCellUrbanAreaChannelRealization::GetPathLoss (void)
{
	/*
	 * Path loss Models from sect. 5.2 in
	 * 3GPP TSG RAN WG4 R4-092042
	 *
	 * Alternative simplified model based on LTE-A evaluation methodology which avoids modeling any walls.
	 */

  double distance;
  double minimumCouplingLoss = 45; //[dB] - see 3GPP TSG RAN WG4 #42bis (R4-070456)
  double floorPenetration = 0.0;
  //18.3 n ((n+2)/(n+1)-0.46)

  if (GetSourceNode ()->GetNodeType () == NetworkNode::TYPE_UE
		  && ( GetDestinationNode ()->GetNodeType () == NetworkNode::TYPE_ENODEB || GetDestinationNode ()->GetNodeType () == NetworkNode::TYPE_HOME_BASE_STATION) )
    {
	  UserEquipment* ue = (UserEquipment*) GetSourceNode ();
	  ENodeB* enb = (ENodeB*) GetDestinationNode ();

	  if( enb->GetCell()->GetCellCenterPosition()->GetCoordinateZ() > 0
			  && ue->IsIndoor()
			     && enb->GetCell()->GetCellCenterPosition()->GetCoordinateZ() != ue->GetCell()->GetCellCenterPosition()->GetCoordinateZ())
	  {
		  int n = (int) abs( enb->GetCell()->GetCellCenterPosition()->GetCoordinateZ() - ue->GetCell()->GetCellCenterPosition()->GetCoordinateZ() );
		  floorPenetration = 18.3 * pow( n, ((n+2)/(n+1)-0.46));
	  }

	  distance =  ue->GetMobilityModel ()->GetAbsolutePosition ()->GetDistance (enb->GetMobilityModel ()->GetAbsolutePosition ());
    }

  else if (GetDestinationNode ()->GetNodeType () == NetworkNode::TYPE_UE
		  && ( GetSourceNode ()->GetNodeType () == NetworkNode::TYPE_ENODEB || GetSourceNode ()->GetNodeType () == NetworkNode::TYPE_HOME_BASE_STATION) )
  {
	  UserEquipment* ue = (UserEquipment*) GetDestinationNode ();
	  ENodeB* enb = (ENodeB*) GetSourceNode ();

	  if( enb->GetCell()->GetCellCenterPosition()->GetCoordinateZ() > 0
			  && ue->IsIndoor()
			  && enb->GetCell()->GetCellCenterPosition()->GetCoordinateZ() != ue->GetCell()->GetCellCenterPosition()->GetCoordinateZ())
	  {
		  int n = (int) abs( enb->GetCell()->GetCellCenterPosition()->GetCoordinateZ() - ue->GetCell()->GetCellCenterPosition()->GetCoordinateZ() );
		  floorPenetration = 18.3 * pow( n, ((n+2)/(n+1)-0.46));
	  }

	  distance =  ue->GetMobilityModel ()->GetAbsolutePosition ()->GetDistance (enb->GetMobilityModel ()->GetAbsolutePosition ());
  }




  m_pathLoss = max( minimumCouplingLoss, 127 + ( 30 * log10 (distance * 0.001) ) + floorPenetration);


  return m_pathLoss;
}
void
NetworkManager::PrintUserPosition (void)
{
  std::vector<UserEquipment*>* users = GetUserEquipmentContainer();
  std::vector<UserEquipment*>::iterator iter;
  UserEquipment *user;

  std::cout << " UserPosition X [at " << Simulator::Init()->Now() << "] ";
  for (iter = users->begin(); iter != users->end(); iter++)
    {
    user = *iter;
    std::cout << user->GetMobilityModel ()->GetAbsolutePosition()->GetCoordinateX() << " ";
    }

  std::cout << "\n UserPosition Y [at " << Simulator::Init()->Now() << "] ";
  for (iter = users->begin(); iter != users->end(); iter++)
    {
    user = *iter;
    std::cout << user->GetMobilityModel ()->GetAbsolutePosition()->GetCoordinateY() << " ";
    }
  std::cout << std::endl;
}
double
WinnerDownlinkChannelRealization::GetPathLoss (void)
{
    /*
     * Path Loss Model For Indoor Environment.
     * "WINNER II channel models, ver 1.1, Tech Report"
     * PL = A*log10(r) + B + C*log10(fc/5) + X; [r in meters; fc in GHz]
     * I = 128.1 – 2GHz
     * X depends on the number of walls in between
     * FL = 17 + 4 (Nfloors - 1) --- floor loss
     */

    double distance;
    UserEquipment* ue;
    ENodeB* enb;

    assert (GetDestinationNode ()->GetNodeType () == NetworkNode::TYPE_HOME_BASE_STATION  || GetSourceNode ()->GetNodeType () == NetworkNode::TYPE_HOME_BASE_STATION);

    if (GetSourceNode ()->GetNodeType () == NetworkNode::TYPE_UE
            && GetDestinationNode ()->GetNodeType () == NetworkNode::TYPE_HOME_BASE_STATION )
    {
        ue = (UserEquipment*) GetSourceNode ();
        enb = (ENodeB*) GetDestinationNode ();

        distance =  ue->GetMobilityModel ()->GetAbsolutePosition ()->GetDistance (enb->GetMobilityModel ()->GetAbsolutePosition ());
    }

    else if (GetDestinationNode ()->GetNodeType () == NetworkNode::TYPE_UE
             && GetSourceNode ()->GetNodeType () == NetworkNode::TYPE_HOME_BASE_STATION )
    {
        ue = (UserEquipment*) GetDestinationNode ();
        enb = (ENodeB*) GetSourceNode ();

        distance =  ue->GetMobilityModel ()->GetAbsolutePosition ()->GetDistance (enb->GetMobilityModel ()->GetAbsolutePosition ());
    }

    int* nbWalls = GetWalls( (Femtocell*) (enb->GetCell()), ue);

    double A, B, C;
    double ExternalWallsAttenuation = 20.0;
    double InternalWallsAttenuation = 10.0;

    if (nbWalls[0] == 0 && nbWalls[1] == 0)
    {   //LOS
        A = 18.7;
        B = 46.8;
        C = 20.0;
    }
    else
    {   //NLOS
        A = 20.0;
        B = 46.4;
        C = 20.0;
    }

    m_pathLoss = A * log10( distance ) +
                 B +
                 C * log10(2. / 5.0) +
                 InternalWallsAttenuation * nbWalls[1] +
                 ExternalWallsAttenuation * nbWalls[0];

    delete [] nbWalls;
    return m_pathLoss;
}
void
NetworkManager::UpdateUserPosition (double time)
{
  std::vector<UserEquipment*> *records = GetUserEquipmentContainer ();
  std::vector<UserEquipment*>::iterator iter;
  UserEquipment *record;

#ifdef MOBILITY_DEBUG
  std::cout << "MOBILITY_DEBUG: UPDATE POSITION, "
      "number of UE = " << records->size () <<
      " time = " << time << std::endl;
#endif

  for (iter = records->begin(); iter != records->end(); iter++)
    {
      record = *iter;

#ifdef MOBILITY_DEBUG
    std::cout << "\t USER  " << record->GetIDNetworkNode ()
	              << std::endl;
#endif

      record->UpdateUserPosition (time);
      record->SetIndoorFlag( CheckIndoorUsers(record) );

#ifdef AMC_MAPPING
  std::cout << "time: " << time << "\n\t position: "
		  << record->GetMobilityModel ()->GetAbsolutePosition ()->GetCoordinateX () <<
		  " " << record->GetMobilityModel ()->GetAbsolutePosition ()->GetCoordinateY ()
		  << std::endl;
#endif
#ifdef MOBILITY_DEBUG
  std::cout << "time: " << time << "\t position: "
		  << record->GetMobilityModel ()->GetAbsolutePosition ()->GetCoordinateX () <<
		  " " << record->GetMobilityModel ()->GetAbsolutePosition ()->GetCoordinateY ()
		  << std::endl;
#endif


      if (record->GetMobilityModel ()->GetHandover () == true)
        {
    	  NetworkNode* targetNode = record->GetTargetNode ();

          if (targetNode->GetProtocolStack ()->GetRrcEntity ()->
        		  GetHandoverEntity ()->CheckHandoverNeed (record))
            {
        	  NetworkNode* newTagertNode = targetNode->GetProtocolStack ()
        			  ->GetRrcEntity ()->GetHandoverEntity ()->GetHoManager ()->m_target;

#ifdef HANDOVER_DEBUG
              std::cout << "** HO ** \t time: " << time << " user " <<  record->GetIDNetworkNode () <<
            		  " old eNB " << targetNode->GetIDNetworkNode () <<
            		  " new eNB " << newTagertNode->GetIDNetworkNode () << std::endl;
#endif
              HandoverProcedure(time, record, targetNode, newTagertNode);
            }
        }
    }

  //PrintUEsForEachCell();
}