/*
 * 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_AUTOCALIBRATIONMESH_HH_
#define _OWLPS_POSITIONING_AUTOCALIBRATIONMESH_HH_

class CapturePoint ;
class Point3D ;

#include "autocalibration.hh"

#include <vector>
#include <unordered_map>

/// Generates reference points in a mesh
class AutocalibrationMesh: public Autocalibration
{
protected:
  struct cp
  {
    const CapturePoint *cp ;
    float weight ; // Weight of the CP in percents
    float angle ;
  } ;

  /// Angle P-RX-O, O being the origin of the trigonometric circle
  float origin_angle ;
  /// Selected transmitter CPs
  std::vector<cp> ref_cps ;
  /// Angles of the transmitter CPs (before M on the trigonometric
  /// circle)
  /**
   * Note that the angles are stored in absolute value.
   */
  std::multimap<double,
      std::pair<double,
      std::unordered_map<
      std::string, CapturePoint>::const_iterator> >
      sorted_negative_angles ;
  /// Angles of the transmitter CPs (after M on the trigonometric circle)
  std::multimap<double,
      std::pair<double,
      std::unordered_map<
      std::string, CapturePoint>::const_iterator> >
      sorted_positive_angles ;

  /// Initialises a struct cp with the values from `s`
  void init_cp(
    const std::map<double, std::pair<double, std::unordered_map<
    std::string, CapturePoint>::const_iterator> >::const_iterator s) ;

  /// Generates the SSs for the current CP
  void generate_ss(void) ;
  /// Sorts the reference CPs for a receiver CP
  void sort_reference_cps(void) ;
  /// Computes the weight of the selected CP(s)
  void weight_cps(void) ;
  /// Weights two CPs according to their angles
  void weight_2_cps(void) ;
  /// Computes a SS with several packets in it
  void compute_multi_packet_ss(void) ;
  /// Computes a SS with only one packet in it
  bool compute_single_packet_ss(pkt_id_t pkt_id) ;
  /// Computes a SS according to the weight of the CP
  double compute_weighted_ss(const unsigned int cp_idx,
                             const pkt_id_t pkt_id,
                             const float point_dst) ;

public:
  AutocalibrationMesh(const Point3D &_point): Autocalibration(_point) {}
} ;

#endif // _OWLPS_POSITIONING_AUTOCALIBRATIONMESH_HH_
