// Copyright 2018 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 <memory>

#include "base/files/scoped_temp_dir.h"
#include "components/drive/chromeos/change_list_loader.h"
#include "components/drive/chromeos/drive_test_util.h"
#include "components/drive/chromeos/loader_controller.h"
#include "components/drive/chromeos/resource_metadata.h"
#include "components/drive/chromeos/team_drive_list_loader.h"
#include "components/drive/event_logger.h"
#include "components/drive/file_system_core_util.h"
#include "components/drive/job_scheduler.h"
#include "components/drive/service/fake_drive_service.h"
#include "components/drive/service/test_util.h"
#include "components/prefs/testing_pref_service.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "google_apis/drive/test_util.h"
#include "services/network/test/test_network_connection_tracker.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace drive {
namespace internal {

namespace {

constexpr char kTestStartPageToken[] = "123456";

class TestTeamDriveListObserver : public TeamDriveListObserver {
 public:
  ~TestTeamDriveListObserver() override = default;

  void OnTeamDriveListLoaded(
      const std::vector<TeamDrive>& team_drives_list,
      const std::vector<TeamDrive>& added_team_drives,
      const std::vector<TeamDrive>& removed_team_drives) override {
    team_drives_list_ = team_drives_list;
    added_team_drives_ = added_team_drives;
    removed_team_drives_ = removed_team_drives;
  }

  const std::vector<TeamDrive>& team_drives_list() const {
    return team_drives_list_;
  }

  const std::vector<TeamDrive>& added_team_drives() const {
    return added_team_drives_;
  }

  const std::vector<TeamDrive>& removed_team_drives() const {
    return removed_team_drives_;
  }

 private:
  std::vector<TeamDrive> team_drives_list_;
  std::vector<TeamDrive> added_team_drives_;
  std::vector<TeamDrive> removed_team_drives_;
};

}  // namespace

class TeamDriveListLoaderTest : public testing::Test {
 protected:
  void SetUp() override {
    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());

    pref_service_ = std::make_unique<TestingPrefServiceSimple>();
    test_util::RegisterDrivePrefs(pref_service_->registry());

    logger_ = std::make_unique<EventLogger>();

    drive_service_ = std::make_unique<FakeDriveService>();
    ASSERT_TRUE(test_util::SetUpTestEntries(drive_service_.get()));
    drive_service_->set_default_max_results(2);

    network::TestNetworkConnectionTracker::GetInstance()->SetConnectionType(
        network::mojom::ConnectionType::CONNECTION_WIFI);
    scheduler_ = std::make_unique<JobScheduler>(
        pref_service_.get(), logger_.get(), drive_service_.get(),
        network::TestNetworkConnectionTracker::GetInstance(),
        base::ThreadTaskRunnerHandle::Get().get(), nullptr);
    metadata_storage_.reset(new ResourceMetadataStorage(
        temp_dir_.GetPath(), base::ThreadTaskRunnerHandle::Get().get()));
    ASSERT_TRUE(metadata_storage_->Initialize());

    cache_.reset(new FileCache(metadata_storage_.get(), temp_dir_.GetPath(),
                               base::ThreadTaskRunnerHandle::Get().get(),
                               nullptr /* free_disk_space_getter */));
    ASSERT_TRUE(cache_->Initialize());

    metadata_.reset(
        new ResourceMetadata(metadata_storage_.get(), cache_.get(),
                             base::ThreadTaskRunnerHandle::Get().get()));
    ASSERT_EQ(FILE_ERROR_OK, metadata_->Initialize());

    loader_controller_ = std::make_unique<LoaderController>();
    team_drive_list_loader_ = std::make_unique<TeamDriveListLoader>(
        logger_.get(), base::ThreadTaskRunnerHandle::Get().get(),
        metadata_.get(), scheduler_.get(), loader_controller_.get());

    team_drive_list_observer_ = std::make_unique<TestTeamDriveListObserver>();
    team_drive_list_loader_->AddObserver(team_drive_list_observer_.get());
  }

  // Creates a ResourceEntry for a directory with explicitly set resource_id.
  ResourceEntry CreateDirectoryEntryWithResourceId(
      const std::string& title,
      const std::string& resource_id,
      const std::string& parent_local_id) {
    ResourceEntry entry;
    entry.set_title(title);
    entry.set_resource_id(resource_id);
    entry.set_parent_local_id(parent_local_id);
    entry.mutable_file_info()->set_is_directory(true);
    entry.mutable_directory_specific_info()->set_start_page_token(
        kTestStartPageToken);
    return entry;
  }

  content::TestBrowserThreadBundle thread_bundle_;
  base::ScopedTempDir temp_dir_;
  std::unique_ptr<TestingPrefServiceSimple> pref_service_;
  std::unique_ptr<EventLogger> logger_;
  std::unique_ptr<FakeDriveService> drive_service_;
  std::unique_ptr<JobScheduler> scheduler_;
  std::unique_ptr<ResourceMetadataStorage, test_util::DestroyHelperForTests>
      metadata_storage_;
  std::unique_ptr<FileCache, test_util::DestroyHelperForTests> cache_;
  std::unique_ptr<ResourceMetadata, test_util::DestroyHelperForTests> metadata_;
  std::unique_ptr<LoaderController> loader_controller_;
  std::unique_ptr<TeamDriveListLoader> team_drive_list_loader_;
  std::unique_ptr<TestTeamDriveListObserver> team_drive_list_observer_;
};

// Tests that if there are no team drives on the server, we will not add
// and team drives to local metadata.
TEST_F(TeamDriveListLoaderTest, NoTeamDrives) {
  // Tests the response if there are no team drives loaded.
  FileError error = FILE_ERROR_FAILED;
  team_drive_list_loader_->LoadIfNeeded(
      google_apis::test_util::CreateCopyResultCallback(&error));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(FILE_ERROR_OK, error);
  EXPECT_EQ(1, drive_service_->team_drive_list_load_count());

  EXPECT_TRUE(team_drive_list_observer_->team_drives_list().empty());
  EXPECT_TRUE(team_drive_list_observer_->added_team_drives().empty());
  EXPECT_TRUE(team_drive_list_observer_->removed_team_drives().empty());

  ResourceEntryVector entries;
  EXPECT_EQ(FILE_ERROR_OK, metadata_->ReadDirectoryByPath(
                               util::GetDriveTeamDrivesRootPath(), &entries));
  EXPECT_TRUE(entries.empty());
}

// Tests if there is one team drive on the server we will add it to the local
// metadata.
TEST_F(TeamDriveListLoaderTest, OneTeamDrive) {
  constexpr char kTeamDriveId1[] = "the1stTeamDriveId";
  constexpr char kTeamDriveName1[] = "The First Team Drive";
  drive_service_->AddTeamDrive(kTeamDriveId1, kTeamDriveName1);

  FileError error = FILE_ERROR_FAILED;
  team_drive_list_loader_->CheckForUpdates(
      google_apis::test_util::CreateCopyResultCallback(&error));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(FILE_ERROR_OK, error);
  EXPECT_EQ(1, drive_service_->team_drive_list_load_count());

  EXPECT_EQ(1UL, team_drive_list_observer_->team_drives_list().size());
  EXPECT_EQ(1UL, team_drive_list_observer_->added_team_drives().size());
  EXPECT_TRUE(team_drive_list_observer_->removed_team_drives().empty());

  ResourceEntryVector entries;
  EXPECT_EQ(FILE_ERROR_OK, metadata_->ReadDirectoryByPath(
                               util::GetDriveTeamDrivesRootPath(), &entries));
  EXPECT_EQ(1UL, entries.size());

  ResourceEntry entry;
  EXPECT_EQ(FILE_ERROR_OK,
            metadata_->GetResourceEntryByPath(
                util::GetDriveTeamDrivesRootPath().AppendASCII(kTeamDriveName1),
                &entry));

  const base::FilePath& team_drive_path =
      team_drive_list_observer_->team_drives_list().front().team_drive_path();
  EXPECT_EQ(team_drive_path,
            util::GetDriveTeamDrivesRootPath().AppendASCII(kTeamDriveName1));
}

TEST_F(TeamDriveListLoaderTest, NotmalizedTeamDriveName) {
  constexpr char kTeamDriveId1[] = "the1stTeamDriveId";
  constexpr char kTeamDriveName1[] = "A / Strange / Team / Drive / Name";
  constexpr char kTeamDriveNormalized1[] = "A _ Strange _ Team _ Drive _ Name";
  drive_service_->AddTeamDrive(kTeamDriveId1, kTeamDriveName1);

  FileError error = FILE_ERROR_FAILED;
  team_drive_list_loader_->CheckForUpdates(
      google_apis::test_util::CreateCopyResultCallback(&error));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(FILE_ERROR_OK, error);
  EXPECT_EQ(1, drive_service_->team_drive_list_load_count());

  EXPECT_EQ(1UL, team_drive_list_observer_->team_drives_list().size());
  EXPECT_EQ(1UL, team_drive_list_observer_->added_team_drives().size());
  EXPECT_TRUE(team_drive_list_observer_->removed_team_drives().empty());

  ResourceEntryVector entries;
  EXPECT_EQ(FILE_ERROR_OK, metadata_->ReadDirectoryByPath(
                               util::GetDriveTeamDrivesRootPath(), &entries));
  EXPECT_EQ(1UL, entries.size());

  ResourceEntry entry;
  EXPECT_EQ(
      FILE_ERROR_OK,
      metadata_->GetResourceEntryByPath(
          util::GetDriveTeamDrivesRootPath().Append(kTeamDriveNormalized1),
          &entry));

  {
    const base::FilePath& team_drive_path =
        team_drive_list_observer_->team_drives_list().front().team_drive_path();
    EXPECT_EQ(team_drive_path,
              util::GetDriveTeamDrivesRootPath().Append(kTeamDriveNormalized1));
  }
  {
    const base::FilePath& team_drive_path =
        team_drive_list_observer_->added_team_drives()
            .front()
            .team_drive_path();
    EXPECT_EQ(team_drive_path,
              util::GetDriveTeamDrivesRootPath().Append(kTeamDriveNormalized1));
  }
}

// Tests if there are multiple team drives on the server, we will add them all
// to local metadata.
TEST_F(TeamDriveListLoaderTest, MultipleTeamDrive) {
  const std::vector<std::pair<std::string, std::string>> team_drives = {
      {"the1stTeamDriveId", "The First Team Drive"},
      {"the2ndTeamDriveId", "The Second Team Drive"},
      {"the3rdTeamDriveId", "The Third Team Drive"},
      {"the4thTeamDriveId", "The Forth Team Drive"},
  };

  for (const auto& drive : team_drives) {
    drive_service_->AddTeamDrive(drive.first, drive.second);
  }

  FileError error = FILE_ERROR_FAILED;
  team_drive_list_loader_->CheckForUpdates(
      google_apis::test_util::CreateCopyResultCallback(&error));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(FILE_ERROR_OK, error);
  EXPECT_EQ(1, drive_service_->team_drive_list_load_count());

  EXPECT_EQ(team_drives.size(),
            team_drive_list_observer_->team_drives_list().size());
  EXPECT_EQ(team_drives.size(),
            team_drive_list_observer_->added_team_drives().size());
  EXPECT_TRUE(team_drive_list_observer_->removed_team_drives().empty());

  ResourceEntryVector entries;
  EXPECT_EQ(FILE_ERROR_OK, metadata_->ReadDirectoryByPath(
                               util::GetDriveTeamDrivesRootPath(), &entries));
  EXPECT_EQ(team_drives.size(), entries.size());

  ResourceEntry entry;

  for (const auto& drive : team_drives) {
    EXPECT_EQ(FILE_ERROR_OK,
              metadata_->GetResourceEntryByPath(
                  util::GetDriveTeamDrivesRootPath().AppendASCII(drive.second),
                  &entry));
    EXPECT_EQ(drive.first, entry.resource_id());
    EXPECT_EQ(drive.second, entry.base_name());
    EXPECT_TRUE(entry.file_info().is_directory());
    EXPECT_EQ("", entry.directory_specific_info().start_page_token());
  }
}

// Tests that is we have existing team drives in local metadata, and we add
// new team drives from the server, that we retain the pre-existing local
// metadata.
TEST_F(TeamDriveListLoaderTest, RetainExistingMetadata) {
  const std::vector<std::pair<std::string, std::string>> new_team_drives = {
      {"the3rdTeamDriveId", "The Third Team Drive"},
      {"the4thTeamDriveId", "The Forth Team Drive"},
  };

  const std::vector<std::pair<std::string, std::string>> old_team_drives = {
      {"the1stTeamDriveId", "The First Team Drive"},
      {"the2ndTeamDriveId", "The Second Team Drive"},
  };

  for (const auto& drive : old_team_drives) {
    drive_service_->AddTeamDrive(drive.first, drive.second);
  }

  for (const auto& drive : new_team_drives) {
    drive_service_->AddTeamDrive(drive.first, drive.second);
  }

  std::string root_local_id;
  ASSERT_EQ(FILE_ERROR_OK,
            metadata_->GetIdByPath(util::GetDriveTeamDrivesRootPath(),
                                   &root_local_id));

  for (const auto& drive : old_team_drives) {
    std::string local_id;
    ASSERT_EQ(FILE_ERROR_OK,
              metadata_->AddEntry(CreateDirectoryEntryWithResourceId(
                                      drive.second, drive.first, root_local_id),
                                  &local_id));
  }

  FileError error = FILE_ERROR_FAILED;
  team_drive_list_loader_->CheckForUpdates(
      google_apis::test_util::CreateCopyResultCallback(&error));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(FILE_ERROR_OK, error);
  EXPECT_EQ(1, drive_service_->team_drive_list_load_count());

  EXPECT_EQ(old_team_drives.size() + new_team_drives.size(),
            team_drive_list_observer_->team_drives_list().size());
  EXPECT_EQ(new_team_drives.size(),
            team_drive_list_observer_->added_team_drives().size());
  EXPECT_TRUE(team_drive_list_observer_->removed_team_drives().empty());

  ResourceEntryVector entries;
  EXPECT_EQ(FILE_ERROR_OK, metadata_->ReadDirectoryByPath(
                               util::GetDriveTeamDrivesRootPath(), &entries));
  EXPECT_EQ(new_team_drives.size() + old_team_drives.size(), entries.size());

  ResourceEntry entry;
  for (const auto& drive : new_team_drives) {
    EXPECT_EQ(FILE_ERROR_OK,
              metadata_->GetResourceEntryByPath(
                  util::GetDriveTeamDrivesRootPath().AppendASCII(drive.second),
                  &entry));
    EXPECT_EQ(drive.first, entry.resource_id());
    EXPECT_EQ(drive.second, entry.base_name());
    EXPECT_TRUE(entry.file_info().is_directory());
    EXPECT_EQ("", entry.directory_specific_info().start_page_token());
  }

  for (const auto& drive : old_team_drives) {
    EXPECT_EQ(FILE_ERROR_OK,
              metadata_->GetResourceEntryByPath(
                  util::GetDriveTeamDrivesRootPath().AppendASCII(drive.second),
                  &entry));
    EXPECT_EQ(drive.first, entry.resource_id());
    EXPECT_EQ(drive.second, entry.base_name());
    EXPECT_TRUE(entry.file_info().is_directory());
    EXPECT_EQ(kTestStartPageToken,
              entry.directory_specific_info().start_page_token());
  }
}

// Tests that if we we had team drives stored locally that are no longer on the
// server that we deleted them correctly.
TEST_F(TeamDriveListLoaderTest, RemoveMissingTeamDriveFromMetadata) {
  const std::vector<std::pair<std::string, std::string>> old_team_drives = {
      {"the1stTeamDriveId", "The First Team Drive"},
      {"the2ndTeamDriveId", "The Second Team Drive"},
  };

  std::string root_local_id;
  ASSERT_EQ(FILE_ERROR_OK,
            metadata_->GetIdByPath(util::GetDriveTeamDrivesRootPath(),
                                   &root_local_id));

  for (const auto& drive : old_team_drives) {
    std::string local_id;
    ASSERT_EQ(FILE_ERROR_OK,
              metadata_->AddEntry(CreateDirectoryEntryWithResourceId(
                                      drive.second, drive.first, root_local_id),
                                  &local_id));
  }

  FileError error = FILE_ERROR_FAILED;
  team_drive_list_loader_->CheckForUpdates(
      google_apis::test_util::CreateCopyResultCallback(&error));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(FILE_ERROR_OK, error);
  EXPECT_EQ(1, drive_service_->team_drive_list_load_count());

  EXPECT_TRUE(team_drive_list_observer_->team_drives_list().empty());
  EXPECT_TRUE(team_drive_list_observer_->added_team_drives().empty());
  EXPECT_EQ(old_team_drives.size(),
            team_drive_list_observer_->removed_team_drives().size());

  ResourceEntry entry;
  for (const auto& drive : old_team_drives) {
    EXPECT_EQ(FILE_ERROR_NOT_FOUND,
              metadata_->GetResourceEntryByPath(
                  util::GetDriveTeamDrivesRootPath().AppendASCII(drive.second),
                  &entry));
  }
}

}  // namespace internal
}  // namespace drive
