// Copyright 2017 The Chromium 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 "services/preferences/persistent_pref_store_impl.h"

#include <utility>

#include "base/auto_reset.h"
#include "base/stl_util.h"
#include "base/values.h"
#include "components/prefs/persistent_pref_store.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/preferences/public/cpp/lib/util.h"

namespace prefs {
namespace {

// Creates a PrefUpdateValuePtr representing |value| at |path|.
mojom::PrefUpdateValuePtr CreatePrefUpdate(const std::vector<std::string>& path,
                                           const base::Value* value) {
  if (path.empty()) {
    return mojom::PrefUpdateValue::NewAtomicUpdate(
        value ? base::make_optional(value->Clone()) : base::nullopt);
  }
  std::vector<mojom::SubPrefUpdatePtr> pref_updates;
  pref_updates.emplace_back(
      base::in_place, path,
      value ? base::make_optional(value->Clone()) : base::nullopt);
  return mojom::PrefUpdateValue::NewSplitUpdates(std::move(pref_updates));
}

// Returns a mojom::PrefUpdateValuePtr for |path| relative to |value|. If the
// full path does not exist, a PrefUpdateValue containing the closest value is
// returned.
//
// For example, for a |path| of {"foo", "bar"}:
//  - with a |value| of
//     {
//       "foo": 1
//     }
//   returns a path {"foo"} and value 1.
//
// - with a |value| of
//     {}
//   returns a path {"foo"} and null value.
//
// - with a |value| of
//     {
//       "foo": {}
//     }
//   returns a path {"foo", "bar"} and null value.
//
// - with a |value| of
//     {
//       "foo": {
//         "bar": "baz"
//       }
//     }
//   returns a path {"foo", "bar"} and value "baz".
mojom::PrefUpdateValuePtr LookupPrefUpdate(const std::vector<std::string>& path,
                                           const base::Value* value) {
  if (!value)
    return CreatePrefUpdate(std::vector<std::string>(), value);

  for (size_t i = 0; i < path.size(); ++i) {
    const base::DictionaryValue* dictionary_value = nullptr;
    if (!value->GetAsDictionary(&dictionary_value) ||
        !dictionary_value->Get(path[i], &value)) {
      return CreatePrefUpdate({path.begin(), path.begin() + i}, value);
    }
  }
  return CreatePrefUpdate(path, value);
}

}  // namespace

class PersistentPrefStoreImpl::Connection : public mojom::PersistentPrefStore {
 public:
  Connection(PersistentPrefStoreImpl* pref_store,
             mojom::PersistentPrefStoreRequest request,
             mojom::PrefStoreObserverPtr observer,
             ObservedPrefs observed_keys)
      : pref_store_(pref_store),
        binding_(this, std::move(request)),
        observer_(std::move(observer)),
        observed_keys_(std::move(observed_keys)) {
    auto error_callback =
        base::Bind(&PersistentPrefStoreImpl::Connection::OnConnectionError,
                   base::Unretained(this));
    binding_.set_connection_error_handler(error_callback);
    observer_.set_connection_error_handler(error_callback);
  }

  ~Connection() override = default;

  void OnPrefValuesChanged(const std::vector<mojom::PrefUpdatePtr>& updates) {
    if (write_in_progress_)
      return;

    std::vector<mojom::PrefUpdatePtr> filtered_updates;
    for (const auto& update : updates) {
      if (base::ContainsKey(observed_keys_, update->key)) {
        filtered_updates.push_back(update->Clone());
      }
    }
    if (!filtered_updates.empty())
      observer_->OnPrefsChanged(std::move(filtered_updates));
  }

 private:
  // mojom::PersistentPrefStore:
  void SetValues(std::vector<mojom::PrefUpdatePtr> updates) override {
    base::AutoReset<bool> scoped_call_in_progress(&write_in_progress_, true);
    pref_store_->SetValues(std::move(updates));
    observer_->OnPrefChangeAck();
  }

  void RequestValue(const std::string& key,
                    const std::vector<std::string>& path) override {
    if (!base::ContainsKey(observed_keys_, key))
      return;

    const base::Value* value = nullptr;
    pref_store_->GetValue(key, &value);
    std::vector<mojom::PrefUpdatePtr> updates;
    updates.emplace_back(base::in_place, key, LookupPrefUpdate(path, value), 0);
    observer_->OnPrefsChanged(std::move(updates));
  }

  void CommitPendingWrite(CommitPendingWriteCallback done_callback) override {
    // Note: PersistentPrefStore's synchronous callback part of the
    // CommitPendingWrite() API isn't supported on mojom::PersistentPrefStore at
    // the moment (see PersistentPrefStoreClient::CommitPendingWrite() for
    // details).
    pref_store_->CommitPendingWrite(std::move(done_callback));
  }
  void SchedulePendingLossyWrites() override {
    pref_store_->SchedulePendingLossyWrites();
  }
  void ClearMutableValues() override { pref_store_->ClearMutableValues(); }
  void OnStoreDeletionFromDisk() override {
    pref_store_->OnStoreDeletionFromDisk();
  }

  void OnConnectionError() { pref_store_->OnConnectionError(this); }

  // Owns |this|.
  PersistentPrefStoreImpl* const pref_store_;

  mojo::Binding<mojom::PersistentPrefStore> binding_;
  mojom::PrefStoreObserverPtr observer_;
  const ObservedPrefs observed_keys_;

  // If true then a write is in progress and any update notifications should be
  // ignored, as those updates would originate from ourselves.
  bool write_in_progress_ = false;

  DISALLOW_COPY_AND_ASSIGN(Connection);
};

PersistentPrefStoreImpl::PersistentPrefStoreImpl(
    scoped_refptr<PersistentPrefStore> backing_pref_store,
    base::OnceClosure on_initialized)
    : backing_pref_store_(backing_pref_store) {
  backing_pref_store_->AddObserver(this);
  if (!backing_pref_store_->IsInitializationComplete()) {
    on_initialized_ = std::move(on_initialized);
    initializing_ = true;
  }
}

PersistentPrefStoreImpl::~PersistentPrefStoreImpl() {
  backing_pref_store_->RemoveObserver(this);
}

mojom::PersistentPrefStoreConnectionPtr
PersistentPrefStoreImpl::CreateConnection(ObservedPrefs observed_prefs) {
  DCHECK(!initializing_);
  if (!backing_pref_store_->IsInitializationComplete()) {
    // |backing_pref_store_| initialization failed.
    return mojom::PersistentPrefStoreConnection::New(
        nullptr, nullptr, backing_pref_store_->GetReadError(),
        backing_pref_store_->ReadOnly());
  }
  mojom::PersistentPrefStorePtrInfo pref_store_info;
  mojom::PrefStoreObserverPtr observer;
  mojom::PrefStoreObserverRequest observer_request =
      mojo::MakeRequest(&observer);
  auto values = FilterPrefs(backing_pref_store_->GetValues(), observed_prefs);
  auto connection = std::make_unique<Connection>(
      this, mojo::MakeRequest(&pref_store_info), std::move(observer),
      std::move(observed_prefs));
  auto* connection_ptr = connection.get();
  connections_.insert(std::make_pair(connection_ptr, std::move(connection)));
  return mojom::PersistentPrefStoreConnection::New(
      mojom::PrefStoreConnection::New(std::move(observer_request),
                                      std::move(*values), true),
      std::move(pref_store_info), backing_pref_store_->GetReadError(),
      backing_pref_store_->ReadOnly());
}

void PersistentPrefStoreImpl::OnPrefValueChanged(const std::string& key) {
  if (write_in_progress_)
    return;

  const base::Value* value = nullptr;
  for (auto& entry : connections_) {
    auto update_value = mojom::PrefUpdateValue::New();
    if (GetValue(key, &value)) {
      update_value->set_atomic_update(value->Clone());
    } else {
      update_value->set_atomic_update(base::nullopt);
    }
    std::vector<mojom::PrefUpdatePtr> updates;
    updates.emplace_back(base::in_place, key, std::move(update_value), 0);
    entry.first->OnPrefValuesChanged(updates);
  }
}

void PersistentPrefStoreImpl::OnInitializationCompleted(bool succeeded) {
  DCHECK(initializing_);
  initializing_ = false;
  std::move(on_initialized_).Run();
}

void PersistentPrefStoreImpl::SetValues(
    std::vector<mojom::PrefUpdatePtr> updates) {
  base::AutoReset<bool> scoped_call_in_progress(&write_in_progress_, true);
  for (auto& entry : connections_)
    entry.first->OnPrefValuesChanged(updates);

  for (auto& update : updates) {
    if (update->value->is_atomic_update()) {
      auto& value = update->value->get_atomic_update();
      if (value) {
        backing_pref_store_->SetValue(
            update->key, base::Value::ToUniquePtrValue(std::move(*value)),
            update->flags);
      } else {
        backing_pref_store_->RemoveValue(update->key, update->flags);
      }
    } else if (update->value->is_split_updates()) {
      base::Value* mutable_value = nullptr;
      base::DictionaryValue* dictionary_value = nullptr;
      std::unique_ptr<base::DictionaryValue> pending_dictionary;
      if (!backing_pref_store_->GetMutableValue(update->key, &mutable_value) ||
          !mutable_value->GetAsDictionary(&dictionary_value)) {
        pending_dictionary = std::make_unique<base::DictionaryValue>();
        dictionary_value = pending_dictionary.get();
      }
      std::set<std::vector<std::string>> updated_paths;
      for (auto& split_update : update->value->get_split_updates()) {
        if (split_update->path.empty())
          continue;

        SetValue(dictionary_value,
                 {split_update->path.begin(), split_update->path.end()},
                 split_update->value ? base::Value::ToUniquePtrValue(
                                           std::move(*split_update->value))
                                     : nullptr);
        updated_paths.insert(std::move(split_update->path));
      }
      if (pending_dictionary) {
        backing_pref_store_->SetValue(
            update->key, std::move(pending_dictionary), update->flags);
      } else {
        backing_pref_store_->ReportSubValuesChanged(
            update->key, std::move(updated_paths), update->flags);
      }
    }
  }
}

bool PersistentPrefStoreImpl::GetValue(const std::string& key,
                                       const base::Value** value) const {
  return backing_pref_store_->GetValue(key, value);
}

void PersistentPrefStoreImpl::CommitPendingWrite(
    base::OnceClosure done_callback) {
  backing_pref_store_->CommitPendingWrite(std::move(done_callback));
}

void PersistentPrefStoreImpl::SchedulePendingLossyWrites() {
  backing_pref_store_->SchedulePendingLossyWrites();
}

void PersistentPrefStoreImpl::ClearMutableValues() {
  backing_pref_store_->ClearMutableValues();
}

void PersistentPrefStoreImpl::OnStoreDeletionFromDisk() {
  backing_pref_store_->OnStoreDeletionFromDisk();
}

void PersistentPrefStoreImpl::OnConnectionError(Connection* connection) {
  connections_.erase(connection);
}

}  // namespace prefs
