#include "LocationTable.hh"

#include "GeoNetworkingTypes.hh"

#include "loggers.hh"

using namespace LibItsGeoNetworking__TypesAndValues;

void LocationTable::add_entry(const LibItsGeoNetworking__TypesAndValues::LongPosVector& p_long_pos_vector) {
  loggers::get_instance().log_msg(">>> LocationTable::add_entry:", p_long_pos_vector);

  std::map<const std::string, std::shared_ptr<LibItsGeoNetworking__TypesAndValues::LongPosVector>>::const_iterator it = _entries_by_mids.find(std::string(oct2str(p_long_pos_vector.gnAddr().mid())));
  if (it == _entries_by_mids.cend()) { // Not found
    // Add it
    loggers::get_instance().log_to_hexa("LocationTable::add_entry: Create new entry: ", p_long_pos_vector.gnAddr().mid());
    std::shared_ptr<LibItsGeoNetworking__TypesAndValues::LongPosVector> lpv(new LibItsGeoNetworking__TypesAndValues::LongPosVector(p_long_pos_vector));
    _entries_by_times.insert(std::pair<const unsigned long, std::shared_ptr<LibItsGeoNetworking__TypesAndValues::LongPosVector>>(static_cast<const unsigned long>(p_long_pos_vector.timestamp__().get_long_long_val()), lpv));
    _entries_by_mids.insert(std::pair<const std::string, std::shared_ptr<LibItsGeoNetworking__TypesAndValues::LongPosVector>>(std::string(oct2str(p_long_pos_vector.gnAddr().mid())), lpv));
  } else {
    // Remove entry from _entries_by_times.insert
    // TODO Update the timestamp
    // Add new entry in _entries_by_times.insert
  }
} // End of add_entry method

const bool LocationTable::has_entry(const OCTETSTRING& p_mid) const
{
  loggers::get_instance().log_to_hexa(">>> LocationTable::has_entry: ", p_mid);
  loggers::get_instance().log(">>> LocationTable::has_entry: l=%d", _entries_by_mids.size());
  //  loggers::get_instance().log_to_hexa(">>> LocationTable::has_entry: ", _entries_by_mids[0]);
  
  std::map<const std::string, std::shared_ptr<LibItsGeoNetworking__TypesAndValues::LongPosVector>>::const_iterator it = _entries_by_mids.find(std::string(oct2str(p_mid)));
  return (it != _entries_by_mids.cend());
}

const LibItsGeoNetworking__TypesAndValues::LongPosVector* LocationTable::get_entry(const OCTETSTRING & p_mid) const {
  loggers::get_instance().log_to_hexa("LocationTable::get_entry: ", p_mid);
  
  // Sanity check
  if (_entries_by_times.empty() || (p_mid.lengthof() != 6)) {
    loggers::get_instance().warning("LocationTable::get_entry: Wrong parameters");
    return nullptr;
  }

  std::map<const std::string, std::shared_ptr<LibItsGeoNetworking__TypesAndValues::LongPosVector>>::const_iterator it = _entries_by_mids.find(std::string(oct2str(p_mid)));
  if (it == _entries_by_mids.cend()) { // Not found
    loggers::get_instance().warning("LocationTable::get_entry: Item not found");
    return nullptr;
  }

  return it->second.get();
} // End of get_entry method
