#include "LocationTable.hh"

#include "GeoNetworkingTypes.hh"

#include "loggers.hh"

using namespace LibItsGeoNetworking__TypesAndValues;

bool compare_octetstring::operator()(const OCTETSTRING& p_os1, const OCTETSTRING& p_os2) const
{
  if (p_os1.lengthof() > p_os2.lengthof()) {
    return false;
  } else if (p_os1.lengthof() < p_os2.lengthof()) {
    return true;
  } else {
    for (int i = 0; i < p_os1.lengthof(); i++) {
      if (p_os1[i].get_octet() < p_os2[i].get_octet()) {
        return true;
      }
    }
  }
  return false;
}

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<OCTETSTRING, std::shared_ptr<LibItsGeoNetworking__TypesAndValues::LongPosVector>>::const_iterator it = _entries_by_mids.find(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_mids.insert(std::pair<OCTETSTRING, std::shared_ptr<LibItsGeoNetworking__TypesAndValues::LongPosVector>>(p_long_pos_vector.gnAddr().mid(), lpv));
    _entries_by_times.insert(std::pair<unsigned long, std::shared_ptr<LibItsGeoNetworking__TypesAndValues::LongPosVector>>(static_cast<unsigned long>(p_long_pos_vector.timestamp__().get_long_long_val()), lpv));
  } else {
    // TODO Update the timestamp
  }
} // 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);
  
  std::map<OCTETSTRING, std::shared_ptr<LibItsGeoNetworking__TypesAndValues::LongPosVector>>::const_iterator it = _entries_by_mids.find(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<OCTETSTRING, std::shared_ptr<LibItsGeoNetworking__TypesAndValues::LongPosVector>>::const_iterator it = _entries_by_mids.find(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
