// Copyright (c) 2012 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 "components/browser_sync/abstract_profile_sync_service_test.h"

#include <utility>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/files/file_path.h"
#include "base/location.h"
#include "base/run_loop.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "components/browser_sync/test_http_bridge_factory.h"
#include "components/browser_sync/test_profile_sync_service.h"
#include "components/sync/driver/glue/sync_backend_host_core.h"
#include "components/sync/driver/sync_api_component_factory_mock.h"
#include "components/sync/engine/sync_manager_factory_for_profile_sync_test.h"
#include "components/sync/engine/test_engine_components_factory.h"
#include "components/sync/protocol/sync.pb.h"
#include "components/sync/syncable/test_user_share.h"
#include "services/network/test/test_network_connection_tracker.h"

using syncer::ModelType;
using syncer::SyncEngineImpl;
using testing::_;
using testing::ByMove;
using testing::Return;

namespace browser_sync {

namespace {

std::unique_ptr<syncer::HttpPostProviderFactory> GetHttpPostProviderFactory(
    syncer::CancelationSignal* signal) {
  return std::make_unique<TestHttpBridgeFactory>();
}

class SyncEngineForProfileSyncTest : public SyncEngineImpl {
 public:
  SyncEngineForProfileSyncTest(
      const base::FilePath& temp_dir,
      invalidation::InvalidationService* invalidator,
      const base::WeakPtr<syncer::SyncPrefs>& sync_prefs,
      base::OnceClosure callback);
  ~SyncEngineForProfileSyncTest() override;

  void Initialize(InitParams params) override;

  void ConfigureDataTypes(ConfigureParams params) override;

 private:
  // Invoked at the start of HandleSyncManagerInitializationOnFrontendLoop.
  // Allows extra initialization work to be performed before the engine comes
  // up.
  base::OnceClosure callback_;

  DISALLOW_COPY_AND_ASSIGN(SyncEngineForProfileSyncTest);
};

SyncEngineForProfileSyncTest::SyncEngineForProfileSyncTest(
    const base::FilePath& temp_dir,
    invalidation::InvalidationService* invalidator,
    const base::WeakPtr<syncer::SyncPrefs>& sync_prefs,
    base::OnceClosure callback)
    : SyncEngineImpl(
          "dummy_debug_name",
          invalidator,
          sync_prefs,
          temp_dir.Append(base::FilePath(FILE_PATH_LITERAL("test")))),
      callback_(std::move(callback)) {}

SyncEngineForProfileSyncTest::~SyncEngineForProfileSyncTest() {}

void SyncEngineForProfileSyncTest::Initialize(InitParams params) {
  params.http_factory_getter = base::Bind(&GetHttpPostProviderFactory);
  params.sync_manager_factory =
      std::make_unique<syncer::SyncManagerFactoryForProfileSyncTest>(
          std::move(callback_),
          network::TestNetworkConnectionTracker::GetInstance());
  params.credentials.email = "testuser@gmail.com";
  params.credentials.sync_token = "token";
  params.restored_key_for_bootstrapping.clear();

  // It'd be nice if we avoided creating the EngineComponentsFactory in the
  // first place, but SyncEngine will have created one by now so we must free
  // it. Grab the switches to pass on first.
  syncer::EngineComponentsFactory::Switches factory_switches =
      params.engine_components_factory->GetSwitches();
  params.engine_components_factory =
      std::make_unique<syncer::TestEngineComponentsFactory>(
          factory_switches, syncer::EngineComponentsFactory::STORAGE_IN_MEMORY,
          nullptr);

  SyncEngineImpl::Initialize(std::move(params));
}

void SyncEngineForProfileSyncTest::ConfigureDataTypes(ConfigureParams params) {
  // The first parameter there should be the set of enabled types.  That's not
  // something we have access to from this strange test harness.  We'll just
  // send back the list of newly configured types instead and hope it doesn't
  // break anything.
  // Posted to avoid re-entrancy issues.
  base::SequencedTaskRunnerHandle::Get()->PostTask(
      FROM_HERE,
      base::BindOnce(
          &SyncEngineForProfileSyncTest::FinishConfigureDataTypesOnFrontendLoop,
          base::Unretained(this), params.to_download, params.to_download,
          syncer::ModelTypeSet(), params.ready_task));
}

}  // namespace

AbstractProfileSyncServiceTest::AbstractProfileSyncServiceTest()
    : data_type_thread_("Extra thread") {
  EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
}

AbstractProfileSyncServiceTest::~AbstractProfileSyncServiceTest() {
  sync_service_->Shutdown();
}

bool AbstractProfileSyncServiceTest::CreateRoot(ModelType model_type) {
  return syncer::TestUserShare::CreateRoot(model_type,
                                           sync_service_->GetUserShare());
}

void AbstractProfileSyncServiceTest::CreateSyncService(
    std::unique_ptr<syncer::SyncClient> sync_client,
    base::OnceClosure initialization_success_callback) {
  ASSERT_TRUE(sync_client);
  ProfileSyncService::InitParams init_params =
      profile_sync_service_bundle_.CreateBasicInitParams(
          ProfileSyncService::AUTO_START, std::move(sync_client));
  sync_service_ =
      std::make_unique<TestProfileSyncService>(std::move(init_params));

  syncer::SyncApiComponentFactoryMock* components =
      profile_sync_service_bundle_.component_factory();
  auto engine = std::make_unique<SyncEngineForProfileSyncTest>(
      temp_dir_.GetPath(),
      profile_sync_service_bundle_.fake_invalidation_service(),
      sync_service_->sync_prefs()->AsWeakPtr(),
      std::move(initialization_success_callback));
  EXPECT_CALL(*components, CreateSyncEngine(_, _, _))
      .WillOnce(Return(ByMove(std::move(engine))));

  sync_service_->sync_prefs()->SetSyncRequested(true);
  sync_service_->sync_prefs()->SetFirstSetupComplete();
}

CreateRootHelper::CreateRootHelper(AbstractProfileSyncServiceTest* test,
                                   ModelType model_type)
    : callback_(base::Bind(&CreateRootHelper::CreateRootCallback,
                           base::Unretained(this))),
      test_(test),
      model_type_(model_type),
      success_(false) {}

CreateRootHelper::~CreateRootHelper() {}

const base::Closure& CreateRootHelper::callback() const {
  return callback_;
}

bool CreateRootHelper::success() {
  return success_;
}

void CreateRootHelper::CreateRootCallback() {
  success_ = test_->CreateRoot(model_type_);
}

}  // namespace browser_sync
