// Copyright 2020 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <algorithm>
#include <iterator>
#include <set>
#include <string>

#include <base/check.h>
#include <base/files/file_path.h>
#include <base/logging.h>
#include <base/notreached.h>
#include <brillo/errors/error.h>
#include <chromeos/dbus/service_constants.h>
#include <libimageloader/manifest.h>

#include "dlcservice/error.h"
#include "dlcservice/ref_count.h"
#include "dlcservice/system_state.h"
#include "dlcservice/utils.h"

using std::set;
using std::string;
using std::unique_ptr;

namespace dlcservice {

const char kRefCountFileName[] = "ref_count.bin";
const char kSessionStarted[] = "started";
const char kUsedByUser[] = "user";
const char kUsedBySystem[] = "system";

const char kSystemUsername[] = "system";

// static
std::unique_ptr<RefCountInterface> RefCountInterface::Create(
    const base::FilePath& prefs_path,
    std::shared_ptr<imageloader::Manifest> manifest) {
  auto used_by = manifest->used_by();
  if (used_by == "user") {
    return std::make_unique<UserRefCount>(prefs_path, manifest);
  } else if (used_by == "system") {
    return std::make_unique<SystemRefCount>(prefs_path, manifest);
  } else {
    NOTREACHED() << "Invalid 'used_by' attribute in manifest: " << used_by;
  }
  return nullptr;
}

RefCountBase::RefCountBase(const base::FilePath& prefs_path,
                           std::shared_ptr<imageloader::Manifest> manifest)
    : last_access_time_us_(0), manifest_(manifest) {
  DCHECK(manifest_) << "Manifest object is not set properly.";

  // Load the ref count proto only if it exists.
  ref_count_path_ = prefs_path.Append(kRefCountFileName);
  if (base::PathExists(ref_count_path_)) {
    RefCountInfo info;
    if (ReadRefCountInfo(ref_count_path_, &info)) {
      for (const auto& user : info.users()) {
        users_.insert(user.sanitized_username());
      }
      last_access_time_us_ = info.last_access_time_us();
    }
  }
}

// static
bool RefCountBase::ReadRefCountInfo(const base::FilePath& path,
                                    RefCountInfo* info) {
  DCHECK(info);
  string info_str;
  if (!base::ReadFileToString(path, &info_str)) {
    PLOG(ERROR) << "Failed to read the ref count proto file: " << path.value();
    return false;
  }
  if (!info->ParseFromString(info_str)) {
    LOG(ERROR) << "Failed to parse the ref count proto file: " << path.value();
    return false;
  }
  return true;
}

bool RefCountBase::InstalledDlc() {
  string username = GetCurrentUserName();
  if (username.empty()) {
    // Probably no user has logged in. So discard.
    return true;
  }

  // If we already have the user, ignore.
  if (users_.find(username) != users_.end())
    return true;

  // Add the current user to the list of users for this DLC.
  users_.insert(username);
  return Persist();
}

bool RefCountBase::UninstalledDlc() {
  string username = GetCurrentUserName();
  if (username.empty()) {
    // Probably no user has logged in. So discard.
    return true;
  }

  auto user_it = users_.find(username);
  // If we don't have this user, ignore.
  if (user_it == users_.end())
    return true;

  // Remove the user from the list of users currently using this DLC.
  users_.erase(user_it);
  return Persist();
}

bool RefCountBase::ShouldPurgeDlc() const {
  // If someone is using it, it should not be removed.
  if (users_.size() != 0) {
    return false;
  }

  // If the last access time has not been set, then we don't know the timeline
  // and this DLC should not be removed.
  if (last_access_time_us_ == 0) {
    return false;
  }

  base::Time last_accessed = base::Time::FromDeltaSinceWindowsEpoch(
      base::Microseconds(last_access_time_us_));
  base::TimeDelta delta_time =
      SystemState::Get()->clock()->Now() - last_accessed;
  return delta_time > base::Days(manifest_->days_to_purge());
}

bool RefCountBase::Persist() {
  last_access_time_us_ = SystemState::Get()
                             ->clock()
                             ->Now()
                             .ToDeltaSinceWindowsEpoch()
                             .InMicroseconds();

  RefCountInfo info;
  info.set_last_access_time_us(last_access_time_us_);
  for (const auto& username : users_) {
    info.add_users()->set_sanitized_username(username);
  }

  string info_str;
  if (!info.SerializeToString(&info_str)) {
    LOG(ERROR) << "Failed to serialize user based ref count proto.";
    return false;
  }
  if (!WriteToFile(ref_count_path_, info_str)) {
    PLOG(ERROR) << "Failed to write user based ref count proto to: "
                << ref_count_path_;
    return false;
  }
  return true;
}

// UserRefCount implementations.
set<string> UserRefCount::device_users_;
unique_ptr<string> UserRefCount::primary_session_username_;

// static
void UserRefCount::SessionChanged(const string& state) {
  if (state == kSessionStarted) {
    device_users_ = ScanDirectory(SystemState::Get()->users_dir());
    SystemState::Get()->session_manager()->RetrievePrimarySessionAsync(
        base::BindRepeating(
            &UserRefCount::OnSuccessRetrievePrimarySessionAsync),
        base::BindRepeating(&UserRefCount::OnErrorRetrievePrimarySessionAsync));
  }
}

// static
void UserRefCount::OnSuccessRetrievePrimarySessionAsyncForTest(
    const std::string& username, const std::string& sanitized_username) {
  OnSuccessRetrievePrimarySessionAsync(username, sanitized_username);
}

// static
void UserRefCount::OnSuccessRetrievePrimarySessionAsync(
    const string& username, const string& sanitized_username) {
  primary_session_username_ = std::make_unique<string>(sanitized_username);
}

// static
void UserRefCount::OnErrorRetrievePrimarySessionAsync(brillo::Error* err) {
  LOG(ERROR) << "Failed to get the primary session's username with error: "
             << Error::ToString(err->Clone());
  primary_session_username_.reset();
}

UserRefCount::UserRefCount(const base::FilePath& prefs_path,
                           std::shared_ptr<imageloader::Manifest> manifest)
    : RefCountBase(prefs_path, manifest) {
  // We are only interested in users that exist on the system. Any other user
  // that don't exist in the system, but is included in the ref count should be
  // ignored. We don't necessarily need to delete these dangling users from the
  // proto file itself because one, that user might come back, and two it
  // doesn't really matter to the logic of ref counts because when we load, we
  // only care about the users we loaded and approved. On the next install or
  // uninstall the correct users will be persisted.
  set<string> intersection;
  std::set_intersection(users_.begin(), users_.end(), device_users_.begin(),
                        device_users_.end(),
                        std::inserter(intersection, intersection.end()));
  users_.swap(intersection);
}

}  // namespace dlcservice
