/*
 * This file is part of the Owl Positioning System (OwlPS) project.
 * It is subject to the copyright notice and license terms in the
 * COPYRIGHT.t2t file found in the top-level directory of this
 * distribution and at
 *   https://code.lm7.fr/mcy/owlps/src/master/COPYRIGHT.t2t
 * No part of the OwlPS Project, including this file, may be copied,
 * modified, propagated, or distributed except according to the terms
 * contained in the COPYRIGHT.t2t file; the COPYRIGHT.t2t file must be
 * distributed along with this file, either separately or by replacing
 * this notice by the COPYRIGHT.t2t file's contents.
 */


#include "capturepoint.hh"
#include "stock.hh"
#include "posexcept.hh"

using namespace std ;



/* *** Operations *** */


double CapturePoint::friis_constant_term() const
{
  double wavelength =
    static_cast<double>(PosUtil::LIGHT_SPEED) / frequency ;
  return antenna_gain + 20 * log10(wavelength) - 20 * log10(4 * M_PI) ;
}


/**
 * @param trx The transmitter CP.
 * @returns The percentage of calibration packets sent by `trx` and
 * received by the CP.
 * @returns 0 if no packet were received from `trx.`
 */
float CapturePoint::
received_calibration_from_cp(const CapturePoint &trx) const
{
  if (this == &trx)
    return 100 ;

  // If no reference point is associated with trx, no CP received
  // any calibration from it:
  const ReferencePoint *ref_trx ;
  try
    {
      ref_trx = &Stock::get_reference_point(trx.coordinates) ;
    }
  catch (element_not_found &e)
    {
      return 0 ;
    }

  // Check if trx sent a calibration request:
  const vector<CalibrationRequest*> &ref_requests =
    ref_trx->get_requests(trx.mac_addr) ;
  if (ref_requests.empty())
    return 0 ;

  // Count the number of messages sent by trx and the number of
  // messages actually received by the CP:
  unsigned int
  received_packets = 0,
  expected_packets = 0 ;
  for (auto cr = ref_requests.begin() ; cr != ref_requests.end() ; ++cr)
    {
      const Measurement *const measurement =
        (*cr)->get_measurement(mac_addr) ;
      if (! measurement)
        continue ;
      received_packets += measurement->get_nb_ss() ;
      expected_packets += (*cr)->get_nb_packets() ;
    }

  if (expected_packets == 0)
    return 0 ;

  // Compute the score (percent):
  float score = received_packets * 100.0 / expected_packets ;
  return score ;
}



/* *** Operators *** */


CapturePoint& CapturePoint::operator=(const CapturePoint &source)
{
  if (this == &source)
    return *this ;

  this->WifiDevice::operator=(source) ;
  coordinates = source.coordinates ;
  frequency = source.frequency ;
  friis_index = source.friis_index ;

  return *this ;
}


bool CapturePoint::operator==(const CapturePoint &source) const
{
  if (this == &source)
    return true ;

  return
    this->WifiDevice::operator==(source) &&
    coordinates == source.coordinates &&
    frequency == source.frequency &&
    friis_index == source.friis_index ;
}



ostream &operator<<(ostream &os, const CapturePoint &cp)
{
  os
      << "Coordinates: " << cp.coordinates << '\n'
      << "Frequency: " << cp.frequency << " Hz" << '\n'
      << "Friis index: " << cp.friis_index << '\n'
      << static_cast<WifiDevice>(cp) ;

  return os ;
}
