// Copyright 2015 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 "leaderd/manager.h"

#include <base/bind.h>
#include <base/format_macros.h>
#include <base/logging.h>
#include <base/strings/stringprintf.h>

#include "leaderd/errors.h"
#include "leaderd/group.h"
#include "leaderd/group_config.h"

using chromeos::ErrorPtr;
using chromeos::dbus_utils::AsyncEventSequencer;
using chromeos::dbus_utils::ExportedObjectManager;
using org::chromium::leaderd::ManagerAdaptor;
using dbus::ObjectPath;

namespace leaderd {

namespace {

const char kGroupObjectPathFormat[] = "/org/chromium/leaderd/groups/%" PRIuS;
const char kPingResponse[] = "Hello world!";

void DoneCallback(bool success) { VLOG(1) << "Done register " << success; }

}  // namespace

Manager::Manager(const scoped_refptr<dbus::Bus>& bus,
                 ExportedObjectManager* object_manager,
                 std::unique_ptr<PeerdClient> peerd_client)
    : bus_(bus),
      dbus_object_{object_manager, bus, ManagerAdaptor::GetObjectPath()},
      peerd_client_(std::move(peerd_client)) {
  peerd_client_->SetDelegate(this);
}

Manager::~Manager() {}

void Manager::RegisterAsync(
    chromeos::dbus_utils::AsyncEventSequencer* sequencer) {
  dbus_adaptor_.RegisterWithDBusObject(&dbus_object_);
  dbus_object_.RegisterAsync(
      sequencer->GetHandler("Failed exporting DBusManager.", true));
}

void Manager::RemoveGroup(const std::string& group) {
  groups_.erase(group);
  if (groups_.empty()) {
    peerd_client_->StopMonitoring();
  }
  PublishService();
}

const std::string& Manager::GetUUID() const { return uuid_; }

std::vector<std::tuple<std::vector<uint8_t>, uint16_t>> Manager::GetIPInfo(
    const std::string& peer_uuid) const {
  return peerd_client_->GetIPInfo(peer_uuid);
}

void Manager::SetWebServerPort(uint16_t port) {
  web_port_ = port;
  PublishService();
}

bool Manager::HandleLeaderDiscover(const std::string& group_id,
                                   std::string* leader_id) {
  auto it = groups_.find(group_id);
  if (it == groups_.end()) {
    VLOG(1) << "Received discover for an unknown group.";
    return false;
  }

  it->second->HandleLeaderDiscover(leader_id);
  return true;
}

bool Manager::HandleLeaderChallenge(const std::string& group_id,
                                    const std::string& challenger_id,
                                    int32_t challenger_score,
                                    std::string* leader_id,
                                    std::string* responder_id) {
  auto it = groups_.find(group_id);
  if (it == groups_.end()) {
    VLOG(1) << "Received challenge for an unknown group.";
    return false;
  }

  it->second->HandleLeaderChallenge(challenger_id, challenger_score,
                                    leader_id, responder_id);
  return true;
}

bool Manager::HandleLeaderAnnouncement(const std::string& group_id,
                                       const std::string& leader_id,
                                       int32_t leader_score) {
  auto it = groups_.find(group_id);
  if (it == groups_.end()) {
    VLOG(1) << "Received announcement for an unknown group.";
    return false;
  }

  it->second->HandleLeaderAnnouncement(leader_id, leader_score);
  return true;
}

bool Manager::JoinGroup(chromeos::ErrorPtr* error, dbus::Message* message,
                        const std::string& in_group_id,
                        const std::map<std::string, chromeos::Any>& options,
                        dbus::ObjectPath* out_group_path) {
  const std::string& dbus_client = message->GetSender();
  LOG(INFO) << "Join group=" << in_group_id << " from " << dbus_client;
  if (in_group_id.empty()) {
    chromeos::Error::AddTo(error, FROM_HERE, errors::kDomain,
                           errors::kBadGroupName,
                           "Expected non-empty group id.");
    return false;
  }
  std::unique_ptr<GroupConfig> config{new GroupConfig()};
  if (!config->Load(options, error)) {
    return false;
  }
  auto it = groups_.find(in_group_id);
  if (it != groups_.end()) {
    // TODO(wiley) confirm these parsed options match the ones on the group.
    *out_group_path = it->second->GetObjectPath();
    return true;
  }

  peerd_client_->StartMonitoring();

  dbus::ObjectPath path{
      base::StringPrintf(kGroupObjectPathFormat, ++last_group_dbus_id_)};
  std::unique_ptr<Group> group{new Group{
      in_group_id, std::move(config), bus_,
      dbus_object_.GetObjectManager().get(), path,
      dbus_client, peerd_client_->GetPeersMatchingGroup(in_group_id), this}};
  scoped_refptr<AsyncEventSequencer> sequencer(new AsyncEventSequencer());
  group->RegisterAsync(sequencer->GetHandler("Failed to expose Group.", true));
  sequencer->OnAllTasksCompletedCall({base::Bind(&DoneCallback)});

  groups_[in_group_id].swap(group);
  *out_group_path = path;

  PublishService();
  return true;
}

std::string Manager::Ping() { return kPingResponse; }

void Manager::OnPeerdAvailable() { PublishService(); }

void Manager::OnPeerdDeath() {
  for (auto& group : groups_) {
    group.second->ClearPeers();
  }
}

void Manager::OnSelfIdChanged(const std::string& uuid) {
  if (uuid_ == uuid) {
    return;
  }
  VLOG(1) << "Setting leaderd identity to " << uuid;
  std::string old_uuid = uuid_;
  uuid_ = uuid;
  for (const auto& joined_group : groups_) {
    if (!old_uuid.empty()) {
      joined_group.second->RemovePeer(old_uuid);
    }
    if (!uuid_.empty()) {
      joined_group.second->AddPeer(uuid_);
    }
  }
}

void Manager::OnPeerGroupsChanged(const std::string& peer_uuid,
                                  const std::set<std::string>& groups) {
  // Tell all the groups about the updated peer
  for (const auto& joined_group : groups_) {
    if (groups.find(joined_group.first) == groups.end()) {
      joined_group.second->RemovePeer(peer_uuid);
    } else {
      joined_group.second->AddPeer(peer_uuid);
    }
  }
}

void Manager::PublishService() {
  if (!web_port_) {
    return;
  }
  std::vector<std::string> groups;
  for (const auto& group : groups_) {
    groups.push_back(group.first);
  }

  peerd_client_->PublishGroups(web_port_, groups);
}

}  // namespace leaderd
