// Copyright (c) 2012 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 "power_manager/common/prefs.h"

#include <memory>
#include <set>
#include <utility>

#include <base/bind.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/location.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>
#include <cros_config/cros_config.h>

#include "power_manager/common/cros_config_prefs_source.h"
#include "power_manager/common/file_prefs_store.h"
#include "power_manager/common/prefs_observer.h"
#include "power_manager/common/util.h"

namespace power_manager {

namespace {

// Default directories where read/write and read-only preference files are
// stored.
constexpr char kReadWritePrefsDir[] = "/var/lib/power_manager";
constexpr char kReadOnlyPrefsDir[] = "/usr/share/power_manager";

// Subdirectory within the read-only prefs dir where board-specific prefs are
// stored.
constexpr char kBoardSpecificPrefsSubdir[] = "board_specific";

// Subdirectory within the read-only prefs dir where model-specific prefs are
// stored.
constexpr char kModelSpecificPrefsSubdir[] = "model_specific";

// Path and key name in CrosConfig database to look up model-specific pref
// subdirectory.
constexpr char kModelSubdirConfigPath[] = "/";
constexpr char kModelSubdirConfigKey[] = "powerd-prefs";

// Minimum time between batches of prefs being written to disk, in
// milliseconds.
const int kDefaultWriteIntervalMs = 1000;

}  // namespace

Prefs::TestApi::TestApi(Prefs* prefs) : prefs_(prefs) {}

Prefs::TestApi::~TestApi() {}

bool Prefs::TestApi::TriggerWriteTimeout() {
  if (!prefs_->write_prefs_timer_.IsRunning())
    return false;

  prefs_->write_prefs_timer_.Stop();
  prefs_->WritePrefs();
  return true;
}

Prefs::Prefs()
    : write_interval_(
          base::TimeDelta::FromMilliseconds(kDefaultWriteIntervalMs)) {}

Prefs::~Prefs() {
  if (write_prefs_timer_.IsRunning())
    WritePrefs();
}

// static
std::unique_ptr<PrefsStoreInterface> Prefs::GetDefaultStore() {
  return std::make_unique<FilePrefsStore>(base::FilePath(kReadWritePrefsDir));
}

// static
PrefsSourceInterfaceVector Prefs::GetDefaultSources() {
  PrefsSourceInterfaceVector sources;

  const base::FilePath read_only_path(kReadOnlyPrefsDir);

  auto config = std::make_unique<brillo::CrosConfig>();
  if (config->InitModel()) {
    // Prior to the introduction of CrosConfigPrefsSource, power prefs were
    // stored in a model-specific subdirectory named by a CrosConfig prop; we
    // need to preserve that behavior until we migrate these existing props.
    std::string model_subdir;
    bool has_model_subdir = config->GetString(
        kModelSubdirConfigPath, kModelSubdirConfigKey, &model_subdir);

    sources.emplace_back(new CrosConfigPrefsSource(std::move(config)));

    if (has_model_subdir) {
      sources.emplace_back(
          new FilePrefsStore(read_only_path.Append(kModelSpecificPrefsSubdir)
                                 .Append(model_subdir)));
    }
  }

  sources.emplace_back(
      new FilePrefsStore(read_only_path.Append(kBoardSpecificPrefsSubdir)));
  sources.emplace_back(new FilePrefsStore(read_only_path));
  return sources;
}

bool Prefs::Init(std::unique_ptr<PrefsStoreInterface> pref_store,
                 PrefsSourceInterfaceVector pref_sources) {
  pref_store_ = std::move(pref_store);
  pref_sources_ = std::move(pref_sources);
  return pref_store_->Watch(
      base::Bind(&Prefs::HandlePrefChanged, base::Unretained(this)));
}

void Prefs::AddObserver(PrefsObserver* observer) {
  DCHECK(observer);
  observers_.AddObserver(observer);
}

void Prefs::RemoveObserver(PrefsObserver* observer) {
  DCHECK(observer);
  observers_.RemoveObserver(observer);
}

void Prefs::HandlePrefChanged(const std::string& name) {
  // Resist the temptation to erase |name| from |prefs_to_write_| here, as
  // it would cause a race:
  // 1. SetInt64() is called and pref is written to disk.
  // 2. SetInt64() is called and and the new value is queued.
  // 3. HandleFileChanged() is called regarding the initial write.
  for (PrefsObserver& observer : observers_)
    observer.OnPrefChanged(name);
}

void Prefs::GetPrefResults(const std::string& name,
                           bool read_all,
                           std::vector<PrefReadResult>* results) {
  CHECK(results);
  results->clear();

  PrefReadResult result;

  // If there's a queued value that'll be written to the store soon,
  // use it instead of reading from disk.
  bool in_store;
  if (prefs_to_write_.count(name)) {
    base::TrimWhitespaceASCII(prefs_to_write_[name], base::TRIM_TRAILING,
                              &result.value);
    in_store = true;
  } else {
    in_store = pref_store_->ReadPrefString(name, &result.value);
  }
  if (in_store) {
    result.source_desc = pref_store_->GetDescription();
    results->push_back(result);
    if (!read_all) {
      return;
    }
  }

  for (const auto& source : pref_sources_) {
    if (source->ReadPrefString(name, &result.value)) {
      result.source_desc = source->GetDescription();
      results->push_back(result);
      if (!read_all) {
        return;
      }
    }
  }
}

bool Prefs::GetString(const std::string& name, std::string* buf) {
  DCHECK(buf);
  std::vector<PrefReadResult> results;
  GetPrefResults(name, false, &results);
  if (results.empty())
    return false;
  *buf = results[0].value;
  return true;
}

bool Prefs::GetInt64(const std::string& name, int64_t* value) {
  DCHECK(value);
  std::vector<PrefReadResult> results;
  GetPrefResults(name, true, &results);

  for (const auto& result : results) {
    if (base::StringToInt64(result.value, value))
      return true;
    else
      LOG(ERROR) << "Unable to parse int64_t from " << result.source_desc;
  }
  return false;
}

bool Prefs::GetDouble(const std::string& name, double* value) {
  DCHECK(value);
  std::vector<PrefReadResult> results;
  GetPrefResults(name, true, &results);

  for (const auto& result : results) {
    if (base::StringToDouble(result.value, value))
      return true;
    else
      LOG(ERROR) << "Unable to parse double from " << result.source_desc;
  }
  return false;
}

bool Prefs::GetBool(const std::string& name, bool* value) {
  int64_t int_value = 0;
  if (!GetInt64(name, &int_value))
    return false;
  *value = int_value != 0;
  return true;
}

void Prefs::SetString(const std::string& name, const std::string& value) {
  prefs_to_write_[name] = value;
  ScheduleWrite();
}

void Prefs::SetInt64(const std::string& name, int64_t value) {
  prefs_to_write_[name] = base::Int64ToString(value);
  ScheduleWrite();
}

void Prefs::SetDouble(const std::string& name, double value) {
  prefs_to_write_[name] = base::DoubleToString(value);
  ScheduleWrite();
}

void Prefs::ScheduleWrite() {
  base::TimeDelta time_since_last_write =
      base::TimeTicks::Now() - last_write_time_;
  if (last_write_time_.is_null() || time_since_last_write >= write_interval_) {
    WritePrefs();
  } else if (!write_prefs_timer_.IsRunning()) {
    write_prefs_timer_.Start(FROM_HERE, write_interval_ - time_since_last_write,
                             this, &Prefs::WritePrefs);
  }
}

void Prefs::WritePrefs() {
  for (const auto& pref_pair : prefs_to_write_) {
    if (!pref_store_->WritePrefString(pref_pair.first, pref_pair.second)) {
      PLOG(ERROR) << "Failed to write to " << pref_store_->GetDescription();
    }
  }
  prefs_to_write_.clear();
  last_write_time_ = base::TimeTicks::Now();
}

}  // namespace power_manager
