// Copyright (c) 2011 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 "chrome/browser/sync/test/integration/preferences_helper.h"

#include "base/prefs/pref_change_registrar.h"
#include "base/prefs/pref_service.h"
#include "base/prefs/scoped_user_pref_update.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sync/test/integration/multi_client_status_change_checker.h"
#include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
#include "chrome/browser/sync/test/integration/sync_datatype_helper.h"
#include "chrome/browser/sync/test/integration/sync_test.h"

using sync_datatype_helper::test;

namespace preferences_helper {

PrefService* GetPrefs(int index) {
  return test()->GetProfile(index)->GetPrefs();
}

PrefService* GetVerifierPrefs() {
  return test()->verifier()->GetPrefs();
}

void ChangeBooleanPref(int index, const char* pref_name) {
  bool new_value = !GetPrefs(index)->GetBoolean(pref_name);
  GetPrefs(index)->SetBoolean(pref_name, new_value);
  if (test()->use_verifier())
    GetVerifierPrefs()->SetBoolean(pref_name, new_value);
}

void ChangeIntegerPref(int index, const char* pref_name, int new_value) {
  GetPrefs(index)->SetInteger(pref_name, new_value);
  if (test()->use_verifier())
    GetVerifierPrefs()->SetInteger(pref_name, new_value);
}

void ChangeInt64Pref(int index, const char* pref_name, int64 new_value) {
  GetPrefs(index)->SetInt64(pref_name, new_value);
  if (test()->use_verifier())
    GetVerifierPrefs()->SetInt64(pref_name, new_value);
}

void ChangeDoublePref(int index, const char* pref_name, double new_value) {
  GetPrefs(index)->SetDouble(pref_name, new_value);
  if (test()->use_verifier())
    GetVerifierPrefs()->SetDouble(pref_name, new_value);
}

void ChangeStringPref(int index,
                      const char* pref_name,
                      const std::string& new_value) {
  GetPrefs(index)->SetString(pref_name, new_value);
  if (test()->use_verifier())
    GetVerifierPrefs()->SetString(pref_name, new_value);
}

void ChangeFilePathPref(int index,
                        const char* pref_name,
                        const base::FilePath& new_value) {
  GetPrefs(index)->SetFilePath(pref_name, new_value);
  if (test()->use_verifier())
    GetVerifierPrefs()->SetFilePath(pref_name, new_value);
}

void ChangeListPref(int index,
                    const char* pref_name,
                    const base::ListValue& new_value) {
  {
    ListPrefUpdate update(GetPrefs(index), pref_name);
    base::ListValue* list = update.Get();
    for (base::ListValue::const_iterator it = new_value.begin();
         it != new_value.end();
         ++it) {
      list->Append((*it)->DeepCopy());
    }
  }

  if (test()->use_verifier()) {
    ListPrefUpdate update_verifier(GetVerifierPrefs(), pref_name);
    base::ListValue* list_verifier = update_verifier.Get();
    for (base::ListValue::const_iterator it = new_value.begin();
         it != new_value.end();
         ++it) {
      list_verifier->Append((*it)->DeepCopy());
    }
  }
}

bool BooleanPrefMatches(const char* pref_name) {
  bool reference_value;
  if (test()->use_verifier()) {
    reference_value = GetVerifierPrefs()->GetBoolean(pref_name);
  } else {
    reference_value = GetPrefs(0)->GetBoolean(pref_name);
  }
  for (int i = 0; i < test()->num_clients(); ++i) {
    if (reference_value != GetPrefs(i)->GetBoolean(pref_name)) {
      DVLOG(1) << "Boolean preference " << pref_name << " mismatched in"
               << " profile " << i << ".";
      return false;
    }
  }
  return true;
}

bool IntegerPrefMatches(const char* pref_name) {
  int reference_value;
  if (test()->use_verifier()) {
    reference_value = GetVerifierPrefs()->GetInteger(pref_name);
  } else {
    reference_value = GetPrefs(0)->GetInteger(pref_name);
  }
  for (int i = 0; i < test()->num_clients(); ++i) {
    if (reference_value != GetPrefs(i)->GetInteger(pref_name)) {
      DVLOG(1) << "Integer preference " << pref_name << " mismatched in"
               << " profile " << i << ".";
      return false;
    }
  }
  return true;
}

bool Int64PrefMatches(const char* pref_name) {
  int64 reference_value;
  if (test()->use_verifier()) {
    reference_value = GetVerifierPrefs()->GetInt64(pref_name);
  } else {
    reference_value = GetPrefs(0)->GetInt64(pref_name);
  }
  for (int i = 0; i < test()->num_clients(); ++i) {
    if (reference_value != GetPrefs(i)->GetInt64(pref_name)) {
      DVLOG(1) << "Integer preference " << pref_name << " mismatched in"
               << " profile " << i << ".";
      return false;
    }
  }
  return true;
}

bool DoublePrefMatches(const char* pref_name) {
  double reference_value;
  if (test()->use_verifier()) {
    reference_value = GetVerifierPrefs()->GetDouble(pref_name);
  } else {
    reference_value = GetPrefs(0)->GetDouble(pref_name);
  }
  for (int i = 0; i < test()->num_clients(); ++i) {
    if (reference_value != GetPrefs(i)->GetDouble(pref_name)) {
      DVLOG(1) << "Double preference " << pref_name << " mismatched in"
               << " profile " << i << ".";
      return false;
    }
  }
  return true;
}

bool StringPrefMatches(const char* pref_name) {
  std::string reference_value;
  if (test()->use_verifier()) {
    reference_value = GetVerifierPrefs()->GetString(pref_name);
  } else {
    reference_value = GetPrefs(0)->GetString(pref_name);
  }
  for (int i = 0; i < test()->num_clients(); ++i) {
    if (reference_value != GetPrefs(i)->GetString(pref_name)) {
      DVLOG(1) << "String preference " << pref_name << " mismatched in"
               << " profile " << i << ".";
      return false;
    }
  }
  return true;
}

bool FilePathPrefMatches(const char* pref_name) {
  base::FilePath reference_value;
  if (test()->use_verifier()) {
    reference_value = GetVerifierPrefs()->GetFilePath(pref_name);
  } else {
    reference_value = GetPrefs(0)->GetFilePath(pref_name);
  }
  for (int i = 0; i < test()->num_clients(); ++i) {
    if (reference_value != GetPrefs(i)->GetFilePath(pref_name)) {
      DVLOG(1) << "base::FilePath preference " << pref_name << " mismatched in"
               << " profile " << i << ".";
      return false;
    }
  }
  return true;
}

bool ListPrefMatches(const char* pref_name) {
  const base::ListValue* reference_value;
  if (test()->use_verifier()) {
    reference_value = GetVerifierPrefs()->GetList(pref_name);
  } else {
    reference_value = GetPrefs(0)->GetList(pref_name);
  }
  for (int i = 0; i < test()->num_clients(); ++i) {
    if (!reference_value->Equals(GetPrefs(i)->GetList(pref_name))) {
      DVLOG(1) << "List preference " << pref_name << " mismatched in"
               << " profile " << i << ".";
      return false;
    }
  }
  return true;
}


namespace {

class PrefMatchChecker : public StatusChangeChecker {
 public:
  explicit PrefMatchChecker(const char* path);
  virtual ~PrefMatchChecker();

  // StatusChangeChecker implementation.
  virtual bool IsExitConditionSatisfied() = 0;
  virtual std::string GetDebugMessage() const OVERRIDE;

  // Wait for condition to become true.
  void Wait();

 protected:
  const char* GetPath() const;

 private:
  void RegisterPrefListener(PrefService* pref_service);

  ScopedVector<PrefChangeRegistrar> pref_change_registrars_;
  const char* path_;
};

PrefMatchChecker::PrefMatchChecker(const char* path) : path_(path) {
}

PrefMatchChecker::~PrefMatchChecker() {
}

std::string PrefMatchChecker::GetDebugMessage() const {
  return base::StringPrintf("Waiting for pref '%s' to match", GetPath());
}

void PrefMatchChecker::Wait() {
  if (test()->use_verifier()) {
    RegisterPrefListener(GetVerifierPrefs());
  }

  for (int i = 0; i < test()->num_clients(); ++i) {
    RegisterPrefListener(GetPrefs(i));
  }

  if (IsExitConditionSatisfied()) {
    return;
  }

  StartBlockingWait();
}

const char* PrefMatchChecker::GetPath() const {
  return path_;
}

void PrefMatchChecker::RegisterPrefListener(PrefService* pref_service) {
  scoped_ptr<PrefChangeRegistrar> registrar(new PrefChangeRegistrar());
  registrar->Init(pref_service);
  registrar->Add(path_,
                 base::Bind(&PrefMatchChecker::CheckExitCondition,
                            base::Unretained(this)));
  pref_change_registrars_.push_back(registrar.release());
}

// Helper class used in the implementation of AwaitListPrefMatches.
class ListPrefMatchChecker : public PrefMatchChecker {
 public:
  explicit ListPrefMatchChecker(const char* path);
  virtual ~ListPrefMatchChecker();

  // Implementation of PrefMatchChecker.
  virtual bool IsExitConditionSatisfied() OVERRIDE;
};

ListPrefMatchChecker::ListPrefMatchChecker(const char* path)
    : PrefMatchChecker(path) {
}

ListPrefMatchChecker::~ListPrefMatchChecker() {
}

bool ListPrefMatchChecker::IsExitConditionSatisfied() {
  return ListPrefMatches(GetPath());
}

// Helper class used in the implementation of AwaitBooleanPrefMatches.
class BooleanPrefMatchChecker : public PrefMatchChecker {
 public:
  explicit BooleanPrefMatchChecker(const char* path);
  virtual ~BooleanPrefMatchChecker();

  // Implementation of PrefMatchChecker.
  virtual bool IsExitConditionSatisfied() OVERRIDE;
};

BooleanPrefMatchChecker::BooleanPrefMatchChecker(const char* path)
    : PrefMatchChecker(path) {
}

BooleanPrefMatchChecker::~BooleanPrefMatchChecker() {
}

bool BooleanPrefMatchChecker::IsExitConditionSatisfied() {
  return BooleanPrefMatches(GetPath());
}

// Helper class used in the implementation of AwaitIntegerPrefMatches.
class IntegerPrefMatchChecker : public PrefMatchChecker {
 public:
  explicit IntegerPrefMatchChecker(const char* path);
  virtual ~IntegerPrefMatchChecker();

  // Implementation of PrefMatchChecker.
  virtual bool IsExitConditionSatisfied() OVERRIDE;
};

IntegerPrefMatchChecker::IntegerPrefMatchChecker(const char* path)
    : PrefMatchChecker(path) {
}

IntegerPrefMatchChecker::~IntegerPrefMatchChecker() {
}

bool IntegerPrefMatchChecker::IsExitConditionSatisfied() {
  return IntegerPrefMatches(GetPath());
}

// Helper class used in the implementation of AwaitStringPrefMatches.
class StringPrefMatchChecker : public PrefMatchChecker {
 public:
  explicit StringPrefMatchChecker(const char* path);
  virtual ~StringPrefMatchChecker();

  // Implementation of PrefMatchChecker.
  virtual bool IsExitConditionSatisfied() OVERRIDE;
};

StringPrefMatchChecker::StringPrefMatchChecker(const char* path)
    : PrefMatchChecker(path) {
}

StringPrefMatchChecker::~StringPrefMatchChecker() {
}

bool StringPrefMatchChecker::IsExitConditionSatisfied() {
  return StringPrefMatches(GetPath());
}

}  //  namespace

bool AwaitListPrefMatches(const char* pref_name) {
  ListPrefMatchChecker checker(pref_name);
  checker.Wait();
  return !checker.TimedOut();
}

bool AwaitBooleanPrefMatches(const char* pref_name) {
  BooleanPrefMatchChecker checker(pref_name);
  checker.Wait();
  return !checker.TimedOut();
}

bool AwaitIntegerPrefMatches(const char* pref_name) {
  IntegerPrefMatchChecker checker(pref_name);
  checker.Wait();
  return !checker.TimedOut();
}

bool AwaitStringPrefMatches(const char* pref_name) {
  StringPrefMatchChecker checker(pref_name);
  checker.Wait();
  return !checker.TimedOut();
}

}  // namespace preferences_helper
