// Copyright 2016 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 "base/macros.h"
#include "base/optional.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "chrome/browser/sync/chrome_sync_client.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
#include "chrome/browser/sync/test/integration/single_client_status_change_checker.h"
#include "chrome/browser/sync/test/integration/status_change_checker.h"
#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
#include "chrome/browser/sync/test/integration/sync_test.h"
#include "components/browser_sync/profile_sync_components_factory_impl.h"
#include "components/browser_sync/profile_sync_service.h"
#include "components/sync/model/fake_model_type_sync_bridge.h"
#include "components/sync/model/metadata_change_list.h"
#include "components/sync/model/model_error.h"
#include "components/sync/model/model_type_change_processor.h"
#include "components/sync/model/model_type_controller_delegate.h"
#include "components/sync/model_impl/client_tag_based_model_type_processor.h"
#include "components/sync/test/fake_server/fake_server_http_post_provider.h"
#include "net/base/network_change_notifier.h"

using browser_sync::ChromeSyncClient;
using browser_sync::ProfileSyncComponentsFactoryImpl;
using syncer::ClientTagBasedModelTypeProcessor;
using syncer::ConflictResolution;
using syncer::FakeModelTypeSyncBridge;
using syncer::ModelTypeChangeProcessor;
using syncer::ModelTypeControllerDelegate;
using syncer::ModelTypeSyncBridge;

namespace {

const char kKey1[] = "key1";
const char kKey2[] = "key2";
const char kKey3[] = "key3";
const char kKey4[] = "key4";
const char kValue1[] = "value1";
const char kValue2[] = "value2";
const char kValue3[] = "value3";
const char kValue4[] = "value4";
const char* kPassphrase = "12345";

// A ChromeSyncClient that provides a ModelTypeControllerDelegate for
// PREFERENCES.
class TestSyncClient : public ChromeSyncClient {
 public:
  TestSyncClient(Profile* profile, ModelTypeSyncBridge* bridge)
      : ChromeSyncClient(profile), bridge_(bridge) {}

  base::WeakPtr<ModelTypeControllerDelegate> GetControllerDelegateForModelType(
      syncer::ModelType type) override {
    return type == syncer::PREFERENCES
               ? static_cast<base::WeakPtr<ModelTypeControllerDelegate>>(
                     bridge_->change_processor()->GetControllerDelegate())
               : ChromeSyncClient::GetControllerDelegateForModelType(type);
  }

 private:
  ModelTypeSyncBridge* const bridge_;
};

// A FakeModelTypeSyncBridge that supports observing ApplySyncChanges.
class TestModelTypeSyncBridge : public FakeModelTypeSyncBridge {
 public:
  class Observer {
   public:
    virtual void OnApplySyncChanges() = 0;
  };

  TestModelTypeSyncBridge()
      : FakeModelTypeSyncBridge(
            std::make_unique<ClientTagBasedModelTypeProcessor>(
                syncer::PREFERENCES,
                /*dump_stack=*/base::RepeatingClosure())) {
    change_processor()->ModelReadyToSync(db().CreateMetadataBatch());
  }

  base::Optional<syncer::ModelError> ApplySyncChanges(
      std::unique_ptr<syncer::MetadataChangeList> metadata_changes,
      syncer::EntityChangeList entity_changes) override {
    auto error = FakeModelTypeSyncBridge::ApplySyncChanges(
        std::move(metadata_changes), entity_changes);
    NotifyObservers();
    return error;
  }

  void AddObserver(Observer* observer) { observers_.insert(observer); }
  void RemoveObserver(Observer* observer) { observers_.erase(observer); }

 private:
  void NotifyObservers() {
    for (Observer* observer : observers_) {
      observer->OnApplySyncChanges();
    }
  }

  std::set<Observer*> observers_;
};

// A StatusChangeChecker for checking the status of keys in a
// TestModelTypeSyncBridge::Store.
class KeyChecker : public StatusChangeChecker,
                   public TestModelTypeSyncBridge::Observer {
 public:
  KeyChecker(TestModelTypeSyncBridge* bridge, const std::string& key)
      : bridge_(bridge), key_(key) {
    bridge_->AddObserver(this);
  }

  ~KeyChecker() override { bridge_->RemoveObserver(this); }

  void OnApplySyncChanges() override { CheckExitCondition(); }

 protected:
  TestModelTypeSyncBridge* const bridge_;
  const std::string key_;
};

// Wait for data for a key to have a certain value.
class DataChecker : public KeyChecker {
 public:
  DataChecker(TestModelTypeSyncBridge* bridge,
              const std::string& key,
              const std::string& value)
      : KeyChecker(bridge, key), value_(value) {}

  bool IsExitConditionSatisfied() override {
    const auto& db = bridge_->db();
    return db.HasData(key_) && db.GetValue(key_) == value_;
  }

  std::string GetDebugMessage() const override {
    return "Waiting for data for key '" + key_ + "' to be '" + value_ + "'.";
  }

 private:
  const std::string value_;
};

// Wait for data for a key to be absent.
class DataAbsentChecker : public KeyChecker {
 public:
  DataAbsentChecker(TestModelTypeSyncBridge* bridge, const std::string& key)
      : KeyChecker(bridge, key) {}

  bool IsExitConditionSatisfied() override {
    return !bridge_->db().HasData(key_);
  }

  std::string GetDebugMessage() const override {
    return "Waiting for data for key '" + key_ + "' to be absent.";
  }
};

// Wait for metadata for a key to be present.
class MetadataPresentChecker : public KeyChecker {
 public:
  MetadataPresentChecker(TestModelTypeSyncBridge* bridge,
                         const std::string& key)
      : KeyChecker(bridge, key) {}

  bool IsExitConditionSatisfied() override {
    return bridge_->db().HasMetadata(key_);
  }

  std::string GetDebugMessage() const override {
    return "Waiting for metadata for key '" + key_ + "' to be present.";
  }
};

// Wait for metadata for a key to be absent.
class MetadataAbsentChecker : public KeyChecker {
 public:
  MetadataAbsentChecker(TestModelTypeSyncBridge* bridge, const std::string& key)
      : KeyChecker(bridge, key) {}

  bool IsExitConditionSatisfied() override {
    return !bridge_->db().HasMetadata(key_);
  }

  std::string GetDebugMessage() const override {
    return "Waiting for metadata for key '" + key_ + "' to be absent.";
  }
};

// Wait for PREFERENCES to no longer be running.
class PrefsNotRunningChecker : public SingleClientStatusChangeChecker {
 public:
  explicit PrefsNotRunningChecker(browser_sync::ProfileSyncService* service)
      : SingleClientStatusChangeChecker(service) {}

  bool IsExitConditionSatisfied() override {
    return !service()->IsDataTypeControllerRunning(syncer::PREFERENCES);
  }

  std::string GetDebugMessage() const override {
    return "Waiting for prefs to be not running.";
  }
};

// Wait for sync cycle failure.
class SyncCycleFailedChecker : public SingleClientStatusChangeChecker {
 public:
  explicit SyncCycleFailedChecker(browser_sync::ProfileSyncService* service)
      : SingleClientStatusChangeChecker(service) {}

  bool IsExitConditionSatisfied() override {
    const syncer::SyncCycleSnapshot& snap = service()->GetLastCycleSnapshot();
    return HasSyncerError(snap.model_neutral_state());
  }

  std::string GetDebugMessage() const override {
    return "Waiting for  sync cycle failure";
  }
};

class TwoClientUssSyncTest : public SyncTest {
 public:
  TwoClientUssSyncTest() : SyncTest(TWO_CLIENT) {
    DisableVerifier();
    sync_client_factory_ = base::Bind(&TwoClientUssSyncTest::CreateSyncClient,
                                      base::Unretained(this));
    ProfileSyncServiceFactory::SetSyncClientFactoryForTest(
        &sync_client_factory_);
    ProfileSyncComponentsFactoryImpl::OverridePrefsForUssTest(true);
    // The test infra creates a profile before the two made for sync tests.
    number_of_clients_ignored_ = 1;
#if defined(OS_CHROMEOS)
    // ChromeOS will force loading a signin profile, so we need to ignore one
    // more client.
    number_of_clients_ignored_ += 1;
#endif
  }

  ~TwoClientUssSyncTest() override {
    ProfileSyncServiceFactory::SetSyncClientFactoryForTest(nullptr);
    ProfileSyncComponentsFactoryImpl::OverridePrefsForUssTest(false);
  }

  void SetUp() override {
    net::NetworkChangeNotifier::SetTestNotificationsOnly(true);
    SyncTest::SetUp();
  }

  bool TestUsesSelfNotifications() override { return false; }

  TestModelTypeSyncBridge* GetModelTypeSyncBridge(int i) {
    return bridges_.at(i).get();
  }

 protected:
  std::unique_ptr<ChromeSyncClient> CreateSyncClient(Profile* profile) {
    if (number_of_clients_ignored_ > 0) {
      --number_of_clients_ignored_;
      return std::make_unique<ChromeSyncClient>(profile);
    }
    auto bridge = std::make_unique<TestModelTypeSyncBridge>();
    auto client = std::make_unique<TestSyncClient>(profile, bridge.get());
    clients_.push_back(client.get());
    bridges_.push_back(std::move(bridge));
    return std::move(client);
  }

  ProfileSyncServiceFactory::SyncClientFactory sync_client_factory_;
  std::vector<std::unique_ptr<TestModelTypeSyncBridge>> bridges_;
  std::vector<TestSyncClient*> clients_;
  size_t number_of_clients_ignored_;

 private:
  DISALLOW_COPY_AND_ASSIGN(TwoClientUssSyncTest);
};

IN_PROC_BROWSER_TEST_F(TwoClientUssSyncTest, Sanity) {
  ASSERT_TRUE(SetupSync());
  ASSERT_EQ(2U, clients_.size());
  ASSERT_EQ(2U, bridges_.size());
  TestModelTypeSyncBridge* model0 = GetModelTypeSyncBridge(0);
  TestModelTypeSyncBridge* model1 = GetModelTypeSyncBridge(1);

  // Add an entity.
  model0->WriteItem(kKey1, kValue1);
  ASSERT_TRUE(DataChecker(model1, kKey1, kValue1).Wait());

  // Update an entity.
  model0->WriteItem(kKey1, kValue2);
  ASSERT_TRUE(DataChecker(model1, kKey1, kValue2).Wait());

  // Delete an entity.
  model0->DeleteItem(kKey1);
  ASSERT_TRUE(DataAbsentChecker(model1, kKey1).Wait());
}

IN_PROC_BROWSER_TEST_F(TwoClientUssSyncTest, DisableEnable) {
  ASSERT_TRUE(SetupSync());
  TestModelTypeSyncBridge* model0 = GetModelTypeSyncBridge(0);
  TestModelTypeSyncBridge* model1 = GetModelTypeSyncBridge(1);

  // Add an entity to test with.
  model0->WriteItem(kKey1, kValue1);
  ASSERT_TRUE(DataChecker(model1, kKey1, kValue1).Wait());
  ASSERT_EQ(1U, model0->db().data_count());
  ASSERT_EQ(1U, model0->db().metadata_count());
  ASSERT_EQ(1U, model1->db().data_count());
  ASSERT_EQ(1U, model1->db().metadata_count());

  // Disable PREFERENCES.
  syncer::ModelTypeSet types = syncer::UserSelectableTypes();
  types.Remove(syncer::PREFERENCES);
  GetSyncService(0)->GetUserSettings()->SetChosenDataTypes(false, types);

  // Wait for it to take effect and remove the metadata.
  ASSERT_TRUE(MetadataAbsentChecker(model0, kKey1).Wait());
  ASSERT_EQ(1U, model0->db().data_count());
  ASSERT_EQ(0U, model0->db().metadata_count());
  // Model 1 should not be affected.
  ASSERT_EQ(1U, model1->db().data_count());
  ASSERT_EQ(1U, model1->db().metadata_count());

  // Re-enable PREFERENCES.
  GetSyncService(0)->GetUserSettings()->SetChosenDataTypes(
      true, syncer::UserSelectableTypes());

  // Wait for metadata to be re-added.
  ASSERT_TRUE(MetadataPresentChecker(model0, kKey1).Wait());
  ASSERT_EQ(1U, model0->db().data_count());
  ASSERT_EQ(1U, model0->db().metadata_count());
  ASSERT_EQ(1U, model1->db().data_count());
  ASSERT_EQ(1U, model1->db().metadata_count());
}

IN_PROC_BROWSER_TEST_F(TwoClientUssSyncTest, ConflictResolution) {
  ASSERT_TRUE(SetupSync());
  TestModelTypeSyncBridge* model0 = GetModelTypeSyncBridge(0);
  TestModelTypeSyncBridge* model1 = GetModelTypeSyncBridge(1);
  model0->SetConflictResolution(ConflictResolution::UseNew(
      FakeModelTypeSyncBridge::GenerateEntityData(kKey1, kValue4)));
  model1->SetConflictResolution(ConflictResolution::UseNew(
      FakeModelTypeSyncBridge::GenerateEntityData(kKey1, kValue4)));

  // Write initial value and wait for it to sync to the other client.
  model0->WriteItem(kKey1, kValue1);
  ASSERT_TRUE(DataChecker(model1, kKey1, kValue1).Wait());

  // Disable network, write value on client 0 and wait for it to attempt
  // committing the value. This client now has conflicting change.
  fake_server::FakeServerHttpPostProvider::DisableNetwork();
  model0->WriteItem(kKey1, kValue2);
  ASSERT_TRUE(SyncCycleFailedChecker(GetSyncService(0)).Wait());

  // Enable network, write different value on client 1 and wait for it to arrive
  // on server. Server now has value different from client 0 which will cause
  // conflict when client 0 performs GetUpdates.
  fake_server::FakeServerHttpPostProvider::EnableNetwork();
  model1->WriteItem(kKey1, kValue3);
  model1->WriteItem(kKey2, kValue1);
  ASSERT_TRUE(ServerCountMatchStatusChecker(syncer::PREFERENCES, 2).Wait());

  // Trigger sync cycle on client 0 by delivering network change notification.
  // Wait for it to resolve conflicting value to kResolutionValue by the custom
  // conflict resolution logic in TestModelTypeSyncBridge.
  net::NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests(
      net::NetworkChangeNotifier::CONNECTION_ETHERNET);
  ASSERT_TRUE(DataChecker(model0, kKey1, kValue4).Wait());

  // Wait for client 1 to settle on resolved value.
  ASSERT_TRUE(DataChecker(model1, kKey1, kValue4).Wait());
}

IN_PROC_BROWSER_TEST_F(TwoClientUssSyncTest, Error) {
  ASSERT_TRUE(SetupSync());
  TestModelTypeSyncBridge* model0 = GetModelTypeSyncBridge(0);
  TestModelTypeSyncBridge* model1 = GetModelTypeSyncBridge(1);

  // Add an entity.
  model0->WriteItem(kKey1, kValue1);
  ASSERT_TRUE(DataChecker(model1, kKey1, kValue1).Wait());

  // Set an error in model 1 to trigger in the next GetUpdates.
  model1->ErrorOnNextCall();
  // Write an item on model 0 to trigger a GetUpdates in model 1.
  model0->WriteItem(kKey1, kValue2);

  // The type should stop syncing but keep tracking metadata.
  ASSERT_TRUE(PrefsNotRunningChecker(GetSyncService(1)).Wait());
  ASSERT_EQ(1U, model1->db().metadata_count());
  model1->WriteItem(kKey2, kValue2);
  ASSERT_EQ(2U, model1->db().metadata_count());
}

IN_PROC_BROWSER_TEST_F(TwoClientUssSyncTest, Encryption) {
  ASSERT_TRUE(SetupSync());
  TestModelTypeSyncBridge* model0 = GetModelTypeSyncBridge(0);
  TestModelTypeSyncBridge* model1 = GetModelTypeSyncBridge(1);

  model0->WriteItem(kKey1, kValue1);
  ASSERT_TRUE(DataChecker(model1, kKey1, kValue1).Wait());

  GetSyncService(0)->GetUserSettings()->SetEncryptionPassphrase(kPassphrase);
  ASSERT_TRUE(PassphraseAcceptedChecker(GetSyncService(0)).Wait());
  // Wait for client 1 to know that a passphrase is happening to avoid potential
  // race conditions and make the functionality this case tests more consistent.
  ASSERT_TRUE(PassphraseRequiredChecker(GetSyncService(1)).Wait());

  model0->WriteItem(kKey1, kValue2);
  model0->WriteItem(kKey2, kValue1);
  model1->WriteItem(kKey3, kValue1);

  ASSERT_TRUE(GetSyncService(1)->GetUserSettings()->SetDecryptionPassphrase(
      kPassphrase));
  ASSERT_TRUE(PassphraseAcceptedChecker(GetSyncService(1)).Wait());

  model0->WriteItem(kKey4, kValue1);

  ASSERT_TRUE(DataChecker(model1, kKey1, kValue2).Wait());
  ASSERT_TRUE(DataChecker(model1, kKey2, kValue1).Wait());
  ASSERT_TRUE(DataChecker(model1, kKey4, kValue1).Wait());

  ASSERT_TRUE(DataChecker(model0, kKey1, kValue2).Wait());
  ASSERT_TRUE(DataChecker(model0, kKey3, kValue1).Wait());
}

}  // namespace
