// Copyright 2013 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/sync_app_list_helper.h"

#include <map>
#include <vector>

#include "base/strings/stringprintf.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sync/test/integration/sync_datatype_helper.h"
#include "chrome/browser/sync/test/integration/sync_test.h"
#include "chrome/browser/ui/app_list/app_list_syncable_service.h"
#include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h"
#include "chrome/browser/ui/app_list/chrome_app_list_item.h"
#include "chrome/browser/ui/app_list/chrome_app_list_model_updater.h"
#include "chrome/common/extensions/sync_helper.h"
#include "extensions/browser/app_sorting.h"
#include "extensions/browser/extension_system.h"

using app_list::AppListSyncableService;
using app_list::AppListSyncableServiceFactory;

SyncAppListHelper* SyncAppListHelper::GetInstance() {
  SyncAppListHelper* instance = base::Singleton<SyncAppListHelper>::get();
  instance->SetupIfNecessary(sync_datatype_helper::test());
  return instance;
}

SyncAppListHelper::SyncAppListHelper()
    : test_(nullptr), setup_completed_(false) {}

SyncAppListHelper::~SyncAppListHelper() {}

void SyncAppListHelper::SetupIfNecessary(SyncTest* test) {
  if (setup_completed_) {
    DCHECK_EQ(test, test_);
    return;
  }
  test_ = test;
  for (auto* profile : test_->GetAllProfiles()) {
    extensions::ExtensionSystem::Get(profile)->InitForRegularProfile(
        true /* extensions_enabled */);
    if (test_->use_verifier() && profile == test_->verifier()) {
      // The default page break items are only installed for first-time users.
      // The verifier() profile doesn't get initialized with remote sync data,
      // and hence the default page breaks are not installed for it. We have to
      // install them manually to avoid a mismatch when comparing the verifier()
      // against other client profiles.
      app_list::AppListSyncableServiceFactory::GetForProfile(profile)
          ->InstallDefaultPageBreaksForTest();
    }
  }

  setup_completed_ = true;
}

bool SyncAppListHelper::AppListMatch(Profile* profile1, Profile* profile2) {
  AppListSyncableService* service1 =
      AppListSyncableServiceFactory::GetForProfile(profile1);
  AppListSyncableService* service2 =
      AppListSyncableServiceFactory::GetForProfile(profile2);
  // Note: sync item entries may not exist in verifier, but item lists should
  // match.
  if (service1->GetModelUpdater()->ItemCount() !=
      service2->GetModelUpdater()->ItemCount()) {
    LOG(ERROR) << "Model item count: "
               << service1->GetModelUpdater()->ItemCount()
               << " != " << service2->GetModelUpdater()->ItemCount();
    return false;
  }
  bool res = true;
  for (size_t i = 0; i < service1->GetModelUpdater()->ItemCount(); ++i) {
    ChromeAppListItem* item1 = service1->GetModelUpdater()->ItemAtForTest(i);
    size_t index2;
    if (!service2->GetModelUpdater()->FindItemIndexForTest(item1->id(),
                                                           &index2)) {
      LOG(ERROR) << " Item(" << i << ") in profile1: " << item1->ToDebugString()
                 << " Not in profile2.";
      res = false;
      continue;
    }

    ChromeAppListItem* item2 =
        service2->GetModelUpdater()->ItemAtForTest(index2);
    if (item1->CompareForTest(item2))
      continue;

    LOG(ERROR) << "Item(" << i << ") in profile1: " << item1->ToDebugString()
               << " != "
               << "Item(" << i << ") in profile2: " << item2->ToDebugString();
    res = false;
  }
  return res;
}

bool SyncAppListHelper::AllProfilesHaveSameAppList() {
  const auto& profiles = test_->GetAllProfiles();
  for (auto* profile : profiles) {
    if (profile != profiles.front() &&
        !AppListMatch(profiles.front(), profile)) {
      DVLOG(1) << "Profile1: "
               << AppListSyncableServiceFactory::GetForProfile(profile);
      PrintAppList(profile);
      DVLOG(1) << "Profile2: " <<
          AppListSyncableServiceFactory::GetForProfile(profiles.front());
      PrintAppList(profiles.front());
      return false;
    }
  }
  return true;
}

void SyncAppListHelper::MoveAppToFolder(Profile* profile,
                                        const std::string& id,
                                        const std::string& folder_id) {
  AppListSyncableService* service =
      AppListSyncableServiceFactory::GetForProfile(profile);
  service->GetModelUpdater()->MoveItemToFolder(id, folder_id);
}

void SyncAppListHelper::MoveAppFromFolder(Profile* profile,
                                          const std::string& id,
                                          const std::string& folder_id) {
  AppListSyncableService* service =
      AppListSyncableServiceFactory::GetForProfile(profile);
  ChromeAppListItem* folder =
      service->GetModelUpdater()->FindFolderItem(folder_id);
  if (!folder) {
    LOG(ERROR) << "Folder not found: " << folder_id;
    return;
  }
  service->GetModelUpdater()->MoveItemToFolder(id, "");
}

void SyncAppListHelper::PrintAppList(Profile* profile) {
  AppListSyncableService* service =
      AppListSyncableServiceFactory::GetForProfile(profile);
  // Build a map from each folder item's id to a list of its child items.
  std::map<const std::string, std::vector<ChromeAppListItem*>> children;
  for (size_t i = 0; i < service->GetModelUpdater()->ItemCount(); ++i) {
    ChromeAppListItem* item = service->GetModelUpdater()->ItemAtForTest(i);
    if (!item->folder_id().empty())
      children[item->folder_id()].push_back(item);
  }
  for (size_t i = 0; i < service->GetModelUpdater()->ItemCount(); ++i) {
    ChromeAppListItem* item = service->GetModelUpdater()->ItemAtForTest(i);
    // Skip if it's not a top level item.
    if (!item->folder_id().empty())
      continue;
    std::string label = base::StringPrintf("Item(%d): ", static_cast<int>(i));
    PrintItem(profile, item, label);
    // Print children if it has any.
    if (children.count(item->id())) {
      DCHECK(item->is_folder());
      auto& child_items = children[item->folder_id()];
      for (size_t j = 0; j < child_items.size(); ++j) {
        ChromeAppListItem* child_item = child_items[j];
        std::string child_label =
            base::StringPrintf(" Folder Item(%d): ", static_cast<int>(j));
        PrintItem(profile, child_item, child_label);
      }
    }
  }
}

void SyncAppListHelper::PrintItem(Profile* profile,
                                  ChromeAppListItem* item,
                                  const std::string& label) {
  extensions::AppSorting* s =
      extensions::ExtensionSystem::Get(profile)->app_sorting();
  std::string id = item->id();
  DVLOG(1) << label << item->ToDebugString()
           << " Page: " << s->GetPageOrdinal(id).ToDebugString().substr(0, 8)
           << " Item: "
           << s->GetAppLaunchOrdinal(id).ToDebugString().substr(0, 8);
}
