// Copyright 2017 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 <algorithm>
#include <string>
#include <utility>

#include "base/bind.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/offline_items_collection/core/offline_content_aggregator.h"
#include "components/offline_items_collection/core/offline_item.h"

namespace offline_items_collection {

namespace {

template <typename T, typename U>
bool MapContainsValue(const std::map<T, U>& map, U value) {
  for (const auto& it : map) {
    if (it.second == value)
      return true;
  }
  return false;
}

}  // namespace

OfflineContentAggregator::OfflineContentAggregator()
    : weak_ptr_factory_(this) {}

OfflineContentAggregator::~OfflineContentAggregator() = default;

std::string OfflineContentAggregator::CreateUniqueNameSpace(
    const std::string& prefix,
    bool is_off_the_record) {
  if (!is_off_the_record)
    return prefix;

  static int num_registrations = 0;
  return prefix + "_" + base::NumberToString(++num_registrations);
}

void OfflineContentAggregator::RegisterProvider(
    const std::string& name_space,
    OfflineContentProvider* provider) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  // Validate that this is the first OfflineContentProvider registered that is
  // associated with |name_space|.
  DCHECK(providers_.find(name_space) == providers_.end());

  // Only set up the connection to the provider if the provider isn't associated
  // with any other namespace.
  if (!MapContainsValue(providers_, provider))
    provider->AddObserver(this);

  providers_[name_space] = provider;
}

void OfflineContentAggregator::UnregisterProvider(
    const std::string& name_space) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  auto provider_it = providers_.find(name_space);

  OfflineContentProvider* provider = provider_it->second;
  providers_.erase(provider_it);
  pending_providers_.erase(provider);

  // Only clean up the connection to the provider if the provider isn't
  // associated with any other namespace.
  if (!MapContainsValue(providers_, provider)) {
    provider->RemoveObserver(this);
  }
}

void OfflineContentAggregator::OpenItem(LaunchLocation location,
                                        const ContentId& id) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  auto it = providers_.find(id.name_space);

  if (it == providers_.end())
    return;

  it->second->OpenItem(location, id);
}

void OfflineContentAggregator::RemoveItem(const ContentId& id) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  auto it = providers_.find(id.name_space);

  if (it == providers_.end())
    return;

  it->second->RemoveItem(id);
}

void OfflineContentAggregator::CancelDownload(const ContentId& id) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  auto it = providers_.find(id.name_space);

  if (it == providers_.end())
    return;

  it->second->CancelDownload(id);
}

void OfflineContentAggregator::PauseDownload(const ContentId& id) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  auto it = providers_.find(id.name_space);

  if (it == providers_.end())
    return;

  it->second->PauseDownload(id);
}

void OfflineContentAggregator::ResumeDownload(const ContentId& id,
                                              bool has_user_gesture) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  auto it = providers_.find(id.name_space);

  if (it == providers_.end())
    return;

  it->second->ResumeDownload(id, has_user_gesture);
}

void OfflineContentAggregator::GetItemById(const ContentId& id,
                                           SingleItemCallback callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  auto it = providers_.find(id.name_space);
  if (it == providers_.end()) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::BindOnce(std::move(callback), base::nullopt));
    return;
  }

  it->second->GetItemById(
      id, base::BindOnce(&OfflineContentAggregator::OnGetItemByIdDone,
                         weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void OfflineContentAggregator::OnGetItemByIdDone(
    SingleItemCallback callback,
    const base::Optional<OfflineItem>& item) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  std::move(callback).Run(item);
}

void OfflineContentAggregator::GetAllItems(MultipleItemCallback callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  // If there is already a call in progress, queue up the callback and wait for
  // the results.
  if (!multiple_item_get_callbacks_.empty()) {
    multiple_item_get_callbacks_.push_back(std::move(callback));
    return;
  }

  DCHECK(aggregated_items_.empty());
  for (auto provider_it : providers_) {
    auto* provider = provider_it.second;

    provider->GetAllItems(
        base::BindOnce(&OfflineContentAggregator::OnGetAllItemsDone,
                       weak_ptr_factory_.GetWeakPtr(), provider));
    pending_providers_.insert(provider);
  }

  if (pending_providers_.empty()) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::BindOnce(std::move(callback), OfflineItemList()));
    return;
  }

  multiple_item_get_callbacks_.push_back(std::move(callback));
}

void OfflineContentAggregator::OnGetAllItemsDone(
    OfflineContentProvider* provider,
    const OfflineItemList& items) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  aggregated_items_.insert(aggregated_items_.end(), items.begin(), items.end());
  pending_providers_.erase(provider);
  if (!pending_providers_.empty()) {
    return;
  }

  auto item_vec = std::move(aggregated_items_);
  auto callbacks = std::move(multiple_item_get_callbacks_);

  for (auto& callback : callbacks)
    std::move(callback).Run(item_vec);
}

void OfflineContentAggregator::GetVisualsForItem(const ContentId& id,
                                                 VisualsCallback callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  auto it = providers_.find(id.name_space);

  if (it == providers_.end()) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::BindOnce(std::move(callback), id, nullptr));
    return;
  }

  it->second->GetVisualsForItem(id, std::move(callback));
}

void OfflineContentAggregator::GetShareInfoForItem(const ContentId& id,
                                                   ShareCallback callback) {
  auto it = providers_.find(id.name_space);

  if (it == providers_.end()) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::BindOnce(std::move(callback), id, nullptr));
    return;
  }

  it->second->GetShareInfoForItem(id, std::move(callback));
}

void OfflineContentAggregator::AddObserver(
    OfflineContentProvider::Observer* observer) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(observer);
  if (observers_.HasObserver(observer))
    return;

  observers_.AddObserver(observer);
}

void OfflineContentAggregator::RemoveObserver(
    OfflineContentProvider::Observer* observer) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(observer);
  if (!observers_.HasObserver(observer))
    return;

  observers_.RemoveObserver(observer);
}

void OfflineContentAggregator::OnItemsAdded(const OfflineItemList& items) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  for (auto& observer : observers_)
    observer.OnItemsAdded(items);
}

void OfflineContentAggregator::OnItemRemoved(const ContentId& id) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  for (auto& observer : observers_)
    observer.OnItemRemoved(id);
}

void OfflineContentAggregator::OnItemUpdated(const OfflineItem& item) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  for (auto& observer : observers_)
    observer.OnItemUpdated(item);
}

}  // namespace offline_items_collection
