// Copyright 2020 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 <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::TimeDelta::FromMicroseconds(last_access_time_us_));
  base::TimeDelta delta_time =
      SystemState::Get()->clock()->Now() - last_accessed;
  return delta_time > base::TimeDelta::FromDays(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
