// 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 "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 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
