// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "services/device/geolocation/position_cache_impl.h"

#include <algorithm>

#include "base/strings/utf_string_conversions.h"
#include "components/device_event_log/device_event_log.h"
#include "services/device/geolocation/wifi_data.h"
#include "services/device/public/mojom/geolocation_internals.mojom.h"
#include "services/device/public/mojom/geoposition.mojom.h"

namespace device {

// static
const size_t PositionCacheImpl::kMaximumSize = 10;
// static
const base::TimeDelta PositionCacheImpl::kMaximumLifetime = base::Days(1);

PositionCacheImpl::CacheEntry::CacheEntry(
    const Hash& hash,
    mojom::GeopositionPtr position,
    std::unique_ptr<base::OneShotTimer> eviction_timer)
    : hash_(hash),
      position_(std::move(position)),
      eviction_timer_(std::move(eviction_timer)) {}
PositionCacheImpl::CacheEntry::~CacheEntry() = default;
PositionCacheImpl::CacheEntry::CacheEntry(CacheEntry&&) = default;
PositionCacheImpl::CacheEntry& PositionCacheImpl::CacheEntry::operator=(
    CacheEntry&&) = default;

// static
PositionCacheImpl::Hash PositionCacheImpl::MakeKey(const WifiData& wifi_data) {
  // Currently we use only WiFi data and base the key only on the MAC addresses.
  std::string key;
  const size_t kCharsPerMacAddress = 6 * 3 + 1;  // e.g. "11:22:33:44:55:66|"
  key.reserve(wifi_data.access_point_data.size() * kCharsPerMacAddress);
  const std::string separator("|");
  for (const auto& access_point_data : wifi_data.access_point_data) {
    key += separator;
    key += access_point_data.mac_address;
    key += separator;
  }
  return key;
}

PositionCacheImpl::PositionCacheImpl(const base::TickClock* clock)
    : clock_(clock) {
  net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
}

PositionCacheImpl::~PositionCacheImpl() {
  net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
}

void PositionCacheImpl::CachePosition(const WifiData& wifi_data,
                                      const mojom::Geoposition& position) {
  const Hash key = MakeKey(wifi_data);

  // If the cache is full, remove the oldest entry.
  if (data_.size() == kMaximumSize) {
    data_.erase(data_.begin());
  }

  DCHECK_LT(data_.size(), kMaximumSize);

  auto eviction_timer = std::make_unique<base::OneShotTimer>(clock_);
  // Ensure that the entry we're adding will be evicted after kMaximumLifetime.
  // base::Unretained safe because the timer is indirectly owned by |this|.
  eviction_timer->Start(FROM_HERE, kMaximumLifetime,
                        base::BindOnce(&PositionCacheImpl::EvictEntry,
                                       base::Unretained(this), key));

  data_.emplace_back(key, position.Clone(), std::move(eviction_timer));
}

const mojom::Geoposition* PositionCacheImpl::FindPosition(
    const WifiData& wifi_data) {
  const Hash key = MakeKey(wifi_data);
  auto it = std::ranges::find_if(
      data_, [key](const CacheEntry& entry) { return entry == key; });
  if (it == data_.end()) {
    ++miss_count_;
    last_miss_ = base::Time::Now();
    return nullptr;
  }
  ++hit_count_;
  last_hit_ = base::Time::Now();
  return it->position();
}

size_t PositionCacheImpl::GetPositionCacheSize() const {
  return data_.size();
}

const mojom::GeopositionResult* PositionCacheImpl::GetLastUsedNetworkPosition()
    const {
  GEOLOCATION_LOG(DEBUG) << "Get last used network position";
  return last_used_result_.get();
}

void PositionCacheImpl::SetLastUsedNetworkPosition(
    const mojom::GeopositionResult& result) {
  last_used_result_ = result.Clone();
}

void PositionCacheImpl::FillDiagnostics(
    mojom::PositionCacheDiagnostics& diagnostics) {
  diagnostics.cache_size = data_.size();
  if (last_hit_) {
    diagnostics.last_hit = *last_hit_;
  }
  if (last_miss_) {
    diagnostics.last_miss = *last_miss_;
  }
  if (hit_count_ || miss_count_) {
    diagnostics.hit_rate =
        static_cast<double>(hit_count_) / (hit_count_ + miss_count_);
  }
  if (last_used_result_) {
    diagnostics.last_network_result = last_used_result_.Clone();
  }
}

void PositionCacheImpl::OnNetworkChanged(
    net::NetworkChangeNotifier::ConnectionType) {
  GEOLOCATION_LOG(DEBUG) << "Network changed";
  // OnNetworkChanged is called " when a change occurs to the host
  // computer's hardware or software that affects the route network packets
  // take to any network server.". This means that whatever position we had
  // stored for a wired connection (empty WifiData) could have become stale.
  EvictEntry(MakeKey(WifiData()));
  last_used_result_.reset();
}

void PositionCacheImpl::EvictEntry(const Hash& hash) {
  std::erase(data_, hash);
}

}  // namespace device
