/*
 * 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.
 */


#ifndef _OWLPS_POSITIONING_ACCESSPOINT_HH_
#define _OWLPS_POSITIONING_ACCESSPOINT_HH_

#include "wifidevice.hh"
#include "point3d.hh"
#include "posutil.hh"

#define CP_DEFAULT_CHANNEL 6
#define CP_DEFAULT_ANTENNA_GAIN 5

/// Represents a [Wi-Fi device](@ref WifiDevice) used for capturing
/// requests
class CapturePoint: public WifiDevice
{
protected:
  Point3D coordinates ;
  unsigned long frequency ; ///< Frequency (channel) in Hz
  float friis_index ; ///< Friis index used by FBCM

public:
  /**
   * Special parameters:
   * - `_antenna_gain` Antenna gain in dBi.
   * - `_trx_power` Transmit power in dBm.
   * - `channel` Wi-Fi channel the CP is listening to (integer
   * between 1 and 14). It will be converted to a frequency in Hz.
   */
  CapturePoint(const Point3D &_coordinates = Point3D(),
               const std::string &_ip_addr = "",
               const std::string &_mac_addr = "",
               const float _antenna_gain = CP_DEFAULT_ANTENNA_GAIN,
               const float _trx_power = WIFIDEVICE_DEFAULT_TRX_POWER,
               const unsigned int &channel = CP_DEFAULT_CHANNEL):
    WifiDevice(_ip_addr, _mac_addr, _antenna_gain, _trx_power),
    coordinates(_coordinates),
    frequency(PosUtil::wifi_channel_to_hz(channel)),
    friis_index(0) {}

  CapturePoint(const WifiDevice &source,
               const Point3D &_coordinates,
               const unsigned int channel = CP_DEFAULT_CHANNEL):
    WifiDevice(source), coordinates(_coordinates),
    frequency(PosUtil::wifi_channel_to_hz(channel)),
    friis_index(0) {}

  explicit CapturePoint(const WifiDevice &source):
    WifiDevice(source), coordinates(Point3D()), frequency(0),
    friis_index(0) {}

  CapturePoint(const CapturePoint &source):
    WifiDevice(source), coordinates(source.coordinates),
    frequency(source.frequency), friis_index(0) {}

  ~CapturePoint(void) {}

  /** @name Read accessors */
  //@{
  const Point3D& get_coordinates(void) const ;
  unsigned long get_frequency(void) const ;
  float get_friis_index(void) const ;
  //@}

  /** @name Write accessors */
  //@{
  void set_coordinates(const Point3D &_coordinates) ;
  void set_channel(const unsigned int channel) ;
  void set_frequency(const unsigned long _frequency) ;
  void set_friis_index(const float _friis_index) ;
  //@}

  /** @name Operations */
  //@{
  /// Returns the Friis formula's constant term
  double friis_constant_term(void) const ;
  /// Computes the percentage of the calibration packets from `trx`
  /// received by the CP
  float received_calibration_from_cp(const CapturePoint &trx) const ;
  //@}

  /** @name Operators */
  //@{
  CapturePoint& operator=(const CapturePoint &source) ;
  bool operator==(const CapturePoint &source) const ;
  bool operator!=(const CapturePoint &source) const ;
  //@}

  /// Displays a CapturePoint
  friend std::ostream &operator<<(std::ostream &os, const CapturePoint &cp) ;
} ;



/* *** Read accessors *** */


inline const Point3D& CapturePoint::get_coordinates() const
{
  return coordinates ;
}


inline unsigned long CapturePoint::get_frequency() const
{
  return frequency ;
}


inline float CapturePoint::get_friis_index() const
{
  return friis_index ;
}



/* *** Write accessors *** */


inline void CapturePoint::set_coordinates(const Point3D &_coordinates)
{
  coordinates = _coordinates ;
}


/**
 * @param channel A Wi-Fi channel (integer between 1 and 14). It will
 * be converted into a frequency in Hz and affected to #frequency. If
 * it is not a Wi-Fi channel number, 0 will be affected to #frequency.
 */
inline void CapturePoint::set_channel(const unsigned int channel)
{
  set_frequency(PosUtil::wifi_channel_to_hz(channel)) ;
}


/**
 * Sets #frequency with the value of the parameter `_frequency.` No
 * control is done, so you should pass a correct value.
 *
 * Note that set_channel() is more secure because a wrong channel
 * number will cause #frequency to be set to zero.
 */
inline void CapturePoint::set_frequency(const unsigned long _frequency)
{
  frequency = _frequency ;
}


inline void CapturePoint::set_friis_index(const float _friis_index)
{
  friis_index = _friis_index ;
}



/* *** Operators *** */


inline bool CapturePoint::operator!=(const CapturePoint &source) const
{
  return !(*this == source) ;
}



#endif // _OWLPS_POSITIONING_ACCESSPOINT_HH_
