// 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/server/peer_update_manager.h"

#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <string>

#include <base/bind.h>
#include <base/logging.h>

using std::string;

using base::FilePath;

namespace p2p {

namespace server {

static size_t GetFileSize(const FilePath& file_path) {
  struct stat statbuf;
  if (stat(file_path.value().c_str(), &statbuf) != 0) {
    PLOG(ERROR) << "Error getting file size for " << file_path.value();
    return 0;
  }
  return statbuf.st_size;
}

PeerUpdateManager::PeerUpdateManager(FileWatcher* file_watcher,
                                     ServicePublisher* publisher,
                                     HttpServer* http_server,
                                     MetricsLibraryInterface* metrics_lib)
    : file_watcher_(file_watcher),
      publisher_(publisher),
      http_server_(http_server),
      metrics_lib_(metrics_lib),
      num_connections_(0) {}

PeerUpdateManager::~PeerUpdateManager() = default;

void PeerUpdateManager::Publish(const FilePath& file) {
  if (file.Extension() == file_watcher_->file_extension()) {
    string id_with_extension = file.BaseName().value();
    string id = id_with_extension.substr(0, id_with_extension.size() - 4);
    size_t file_size = GetFileSize(file);
    publisher_->AddFile(id, file_size);
    UpdateHttpServer();
  }
}

void PeerUpdateManager::Unpublish(const FilePath& file) {
  if (file.Extension() == file_watcher_->file_extension()) {
    string id_with_extension = file.BaseName().value();
    string id = id_with_extension.substr(0, id_with_extension.size() - 4);
    publisher_->RemoveFile(id);
    UpdateHttpServer();
  }
}

void PeerUpdateManager::Update(const FilePath& file) {
  if (file.Extension() == file_watcher_->file_extension()) {
    string id_with_extension = file.BaseName().value();
    string id = id_with_extension.substr(0, id_with_extension.size() - 4);
    size_t file_size = GetFileSize(file);
    publisher_->UpdateFileSize(id, file_size);
  }
}

void PeerUpdateManager::UpdateFileCountMetric() {
  int num_files = publisher_->files().size();
  if (num_files == last_num_files_)
    return;
  last_num_files_ = num_files;

  // Report P2P.Server.FileCount every time a file is added (Publish) or
  // removed (Unpublish).
  string metric = "P2P.Server.FileCount";
  LOG(INFO) << "Uploading " << metric << " (count) for metric " << num_files;
  metrics_lib_->SendToUMA(metric, num_files, 0 /* min */, 50 /* max */, 50);
}

void PeerUpdateManager::UpdateHttpServer() {
  int num_files = publisher_->files().size();
  if (num_files > 0) {
    if (!http_server_->IsRunning()) {
      http_server_->Start();
    }
  } else {
    if (http_server_->IsRunning()) {
      http_server_->Stop();
      UpdateNumConnections(0);
    }
  }
}

void PeerUpdateManager::UpdateNumConnections(int num_connections) {
  if (num_connections_ != num_connections) {
    num_connections_ = num_connections;
    publisher_->SetNumConnections(num_connections);
  }
}

void PeerUpdateManager::OnFileWatcherChanged(
    const FilePath& file, FileWatcher::EventType event_type) {
  VLOG(2) << "FileWatcher changed, path=" << file.value()
          << ", event_type=" << event_type;

  switch (event_type) {
    case FileWatcher::EventType::kFileAdded:
      Publish(file);
      UpdateFileCountMetric();
      break;

    case FileWatcher::EventType::kFileRemoved:
      Unpublish(file);
      UpdateFileCountMetric();
      break;

    case FileWatcher::EventType::kFileChanged:
      Update(file);
      break;
  }
}

void PeerUpdateManager::OnHttpServerNumConnectionsChanged(int num_connections) {
  UpdateNumConnections(num_connections);
}

void PeerUpdateManager::Init() {
  http_server_->SetNumConnectionsCallback(
      base::Bind(&PeerUpdateManager::OnHttpServerNumConnectionsChanged,
                 base::Unretained(this)));

  for (auto const& file : file_watcher_->files()) {
    Publish(file);
  }
  last_num_files_ = publisher_->files().size();

  // TODO(zeuthen): Move to AddChangedCallback() for multiple
  // listeners. Or delegate pattern?
  file_watcher_->SetChangedCallback(base::Bind(
      &PeerUpdateManager::OnFileWatcherChanged, base::Unretained(this)));
}

}  // namespace server

}  // namespace p2p
