// 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() {}

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
