// 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/check.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";

// 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->Init()) {
    sources.emplace_back(new CrosConfigPrefsSource(std::move(config)));
  }

  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::NumberToString(value);
  ScheduleWrite();
}

void Prefs::SetDouble(const std::string& name, double value) {
  prefs_to_write_[name] = base::NumberToString(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
