// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "p2p/client/fake_service_finder.h"

#include <base/logging.h>

#include <set>

using std::map;
using std::set;
using std::string;
using std::vector;

namespace p2p {

namespace client {

FakeServiceFinder::FakeServiceFinder()
    : num_lookup_calls_(0),
    service_filtered_(false) {
}

FakeServiceFinder::~FakeServiceFinder() {
}

vector<const Peer*> FakeServiceFinder::GetPeersForFile(
    const string& file) const {
  vector<const Peer*> res;
  if (service_filtered_)
    return res;

  for (auto const& peer : peers_) {
    if (peer.files.find(file) != peer.files.end())
      res.push_back(&peer);
  }
  return res;
}

vector<string> FakeServiceFinder::AvailableFiles() const {
  if (service_filtered_)
    return vector<string>();

  set<string> retset;
  for (auto const& peer : peers_) {
    for (auto const& file : peer.files) {
      retset.insert(file.first);
    }
  }
  return vector<string>(retset.begin(), retset.end());
}

int FakeServiceFinder::NumTotalConnections() const {
  int res = 0;
  if (service_filtered_)
    return res;

  for (auto const& peer : peers_)
    res += peer.num_connections;
  return res;
}

int FakeServiceFinder::NumTotalPeers() const {
  if (service_filtered_)
    return 0;
  return peers_.size();
}

bool FakeServiceFinder::Lookup() {
  num_lookup_calls_++;

  // Execute scheduled calls.
  if (set_peer_connections_calls_.find(num_lookup_calls_) !=
      set_peer_connections_calls_.end()) {
    for (auto const& params : set_peer_connections_calls_[num_lookup_calls_])
      SetPeerConnections(params.peer_id, params.connections);
    set_peer_connections_calls_.erase(num_lookup_calls_);
  }

  if (remove_available_file_calls_.find(num_lookup_calls_) !=
      remove_available_file_calls_.end()) {
    for (auto const& params : remove_available_file_calls_[num_lookup_calls_])
      RemoveAvailableFile(params);
    remove_available_file_calls_.erase(num_lookup_calls_);
  }

  if (peer_share_file_calls_.find(num_lookup_calls_) !=
      peer_share_file_calls_.end()) {
    for (auto const& params : peer_share_file_calls_[num_lookup_calls_])
      PeerShareFile(params.peer_id, params.file, params.size);
    peer_share_file_calls_.erase(num_lookup_calls_);
  }

  return !service_filtered_;
}

void FakeServiceFinder::Abort() {
}

int FakeServiceFinder::GetNumLookupCalls() {
  return num_lookup_calls_;
}

void FakeServiceFinder::SetServiceFiltered(bool filtered) {
  service_filtered_ = filtered;
}

int FakeServiceFinder::NewPeer(string address, bool is_ipv6, uint16_t port) {
  peers_.push_back((Peer){
      .address = address,
      .is_ipv6 = is_ipv6,
      .port = port,
      .num_connections = 0,
      .files = map<string, size_t>()});
  return peers_.size() - 1;
}

bool FakeServiceFinder::SetPeerConnections(int peer_id, int  connections) {
  if (peer_id < 0 || static_cast<unsigned>(peer_id) >= peers_.size()) {
    LOG(ERROR) << "Invalid peer_id provided: " << peer_id << ".";
    return false;
  }
  peers_[peer_id].num_connections = connections;
  return true;
}

bool FakeServiceFinder::SetPeerConnectionsOnLookup(int at_call,
                                                   int peer_id,
                                                   int connections) {
  if (at_call < num_lookup_calls_)
    return false;
  if (at_call == num_lookup_calls_)
    return SetPeerConnections(peer_id, connections);
  set_peer_connections_calls_[at_call].push_back(
      (SetPeerConnectionsCall){
          .peer_id = peer_id,
          .connections = connections});
  return true;
}

bool FakeServiceFinder::PeerShareFile(int peer_id,
                                      const string& file,
                                      size_t size) {
  if (peer_id < 0 || static_cast<unsigned>(peer_id) >= peers_.size()) {
    LOG(ERROR) << "Invalid peer_id provided: " << peer_id << ".";
    return false;
  }
  peers_[peer_id].files[file] = size;
  return true;
}

bool FakeServiceFinder::PeerShareFileOnLookup(int at_call,
                                              int peer_id,
                                              const std::string& file,
                                              size_t size) {
  if (at_call < num_lookup_calls_)
    return false;
  if (at_call == num_lookup_calls_)
    return PeerShareFile(peer_id, file, size);
  peer_share_file_calls_[at_call].push_back(
      (PeerShareFileCall){
          .peer_id = peer_id,
          .file = file,
          .size = size});
  return true;
}

bool FakeServiceFinder::RemoveAvailableFile(const string& file) {
  int removed = 0;

  for (auto& peer : peers_) {
    map<string, size_t>::iterator file_it = peer.files.find(file);
    if (file_it != peer.files.end()) {
      peer.files.erase(file_it);
      removed++;
    }
  }

  if (!removed) {
    LOG(ERROR) << "Removing unexisting file <" << file << ">.";
    return false;
  }
  return true;
}

bool FakeServiceFinder::RemoveAvailableFileOnLookup(int at_call,
                                                    const std::string& file) {
  if (at_call < num_lookup_calls_)
    return false;
  if (at_call == num_lookup_calls_)
    return RemoveAvailableFile(file);
  // Ensure the RemoveAvailableFile() calls before the PeerShareFile() ones.
  if (peer_share_file_calls_.find(at_call) != peer_share_file_calls_.end())
    return false;
  remove_available_file_calls_[at_call].push_back(file);
  return true;
}

}  // namespace client

}  // namespace p2p
