// 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 "ios/chrome/browser/reading_list/reading_list_download_service.h"

#include <memory>
#include <utility>

#include "base/bind.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
#include "base/task/post_task.h"
#include "components/reading_list/core/offline_url_utils.h"
#include "components/reading_list/core/reading_list_entry.h"
#include "components/reading_list/core/reading_list_model.h"
#include "ios/chrome/browser/application_context.h"
#include "ios/chrome/browser/reading_list/reading_list_distiller_page_factory.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"

namespace {
// Status of the download when it ends, for UMA report.
// These match tools/metrics/histograms/histograms.xml.
enum UMADownloadStatus {
  // The download was successful.
  SUCCESS = 0,
  // The download failed and it won't be retried.
  FAILURE = 1,
  // The download failed and it will be retried.
  RETRY = 2,
  // Add new enum above STATUS_MAX.
  STATUS_MAX
};

// Number of time the download must fail before the download occurs only in
// wifi.
const int kNumberOfFailsBeforeWifiOnly = 5;
// Number of time the download must fail before we give up trying to download
// it.
const int kNumberOfFailsBeforeStop = 7;

// Scans |root| directory and deletes all subdirectories not listed
// in |directories_to_keep|.
// Must be called on File thread.
void CleanUpFiles(base::FilePath root,
                  const std::set<std::string>& processed_directories) {
  base::FileEnumerator file_enumerator(root, false,
                                       base::FileEnumerator::DIRECTORIES);
  for (base::FilePath sub_directory = file_enumerator.Next();
       !sub_directory.empty(); sub_directory = file_enumerator.Next()) {
    std::string directory_name = sub_directory.BaseName().value();
    if (!processed_directories.count(directory_name)) {
      base::DeleteFile(sub_directory, true);
    }
  }
}

}  // namespace

ReadingListDownloadService::ReadingListDownloadService(
    ReadingListModel* reading_list_model,
    PrefService* prefs,
    base::FilePath chrome_profile_path,
    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
    std::unique_ptr<dom_distiller::DistillerFactory> distiller_factory,
    std::unique_ptr<reading_list::ReadingListDistillerPageFactory>
        distiller_page_factory)
    : reading_list_model_(reading_list_model),
      chrome_profile_path_(chrome_profile_path),
      had_connection_(
          !GetApplicationContext()->GetNetworkConnectionTracker()->IsOffline()),
      distiller_page_factory_(std::move(distiller_page_factory)),
      distiller_factory_(std::move(distiller_factory)),
      weak_ptr_factory_(this) {
  DCHECK(reading_list_model);

  url_downloader_ = std::make_unique<URLDownloader>(
      distiller_factory_.get(), distiller_page_factory_.get(), prefs,
      chrome_profile_path, url_loader_factory,
      base::Bind(&ReadingListDownloadService::OnDownloadEnd,
                 base::Unretained(this)),
      base::Bind(&ReadingListDownloadService::OnDeleteEnd,
                 base::Unretained(this)));

  GetApplicationContext()
      ->GetNetworkConnectionTracker()
      ->AddNetworkConnectionObserver(this);
}

ReadingListDownloadService::~ReadingListDownloadService() {
  GetApplicationContext()
      ->GetNetworkConnectionTracker()
      ->RemoveNetworkConnectionObserver(this);
}

void ReadingListDownloadService::Initialize() {
  reading_list_model_->AddObserver(this);
}

base::FilePath ReadingListDownloadService::OfflineRoot() const {
  return reading_list::OfflineRootDirectoryPath(chrome_profile_path_);
}

void ReadingListDownloadService::Shutdown() {
  reading_list_model_->RemoveObserver(this);
}

void ReadingListDownloadService::ReadingListModelLoaded(
    const ReadingListModel* model) {
  DCHECK_EQ(reading_list_model_, model);
  SyncWithModel();
}

void ReadingListDownloadService::ReadingListWillRemoveEntry(
    const ReadingListModel* model,
    const GURL& url) {
  DCHECK_EQ(reading_list_model_, model);
  DCHECK(model->GetEntryByURL(url));
  RemoveDownloadedEntry(url);
}

void ReadingListDownloadService::ReadingListDidAddEntry(
    const ReadingListModel* model,
    const GURL& url,
    reading_list::EntrySource source) {
  DCHECK_EQ(reading_list_model_, model);
  ProcessNewEntry(url);
}

void ReadingListDownloadService::ReadingListDidMoveEntry(
    const ReadingListModel* model,
    const GURL& url) {
  DCHECK_EQ(reading_list_model_, model);
  ProcessNewEntry(url);
}

void ReadingListDownloadService::Clear() {
  distiller_page_factory_->ReleaseAllRetainedWebState();
}

void ReadingListDownloadService::ProcessNewEntry(const GURL& url) {
  const ReadingListEntry* entry = reading_list_model_->GetEntryByURL(url);
  if (!entry || entry->IsRead()) {
    url_downloader_->CancelDownloadOfflineURL(url);
  } else {
    ScheduleDownloadEntry(url);
  }
}

void ReadingListDownloadService::SyncWithModel() {
  DCHECK(reading_list_model_->loaded());
  std::set<std::string> processed_directories;
  std::set<GURL> unprocessed_entries;
  for (const auto& url : reading_list_model_->Keys()) {
    const ReadingListEntry* entry = reading_list_model_->GetEntryByURL(url);
    switch (entry->DistilledState()) {
      case ReadingListEntry::PROCESSED:
        processed_directories.insert(reading_list::OfflineURLDirectoryID(url));
        break;
      case ReadingListEntry::WAITING:
      case ReadingListEntry::PROCESSING:
      case ReadingListEntry::WILL_RETRY:
        unprocessed_entries.insert(url);
        break;
      case ReadingListEntry::DISTILLATION_ERROR:
        break;
    }
  }
  base::PostTaskWithTraitsAndReply(
      FROM_HERE,
      {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
       base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
      base::Bind(&::CleanUpFiles, OfflineRoot(), processed_directories),
      base::Bind(&ReadingListDownloadService::DownloadUnprocessedEntries,
                 base::Unretained(this), unprocessed_entries));
}

void ReadingListDownloadService::DownloadUnprocessedEntries(
    const std::set<GURL>& unprocessed_entries) {
  for (const GURL& url : unprocessed_entries) {
    this->ScheduleDownloadEntry(url);
  }
}

void ReadingListDownloadService::ScheduleDownloadEntry(const GURL& url) {
  DCHECK(reading_list_model_->loaded());
  const ReadingListEntry* entry = reading_list_model_->GetEntryByURL(url);
  if (!entry ||
      entry->DistilledState() == ReadingListEntry::DISTILLATION_ERROR ||
      entry->DistilledState() == ReadingListEntry::PROCESSED || entry->IsRead())
    return;
  GURL local_url(url);
  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
      FROM_HERE,
      base::Bind(&ReadingListDownloadService::DownloadEntry,
                 weak_ptr_factory_.GetWeakPtr(), local_url),
      entry->TimeUntilNextTry());
}

void ReadingListDownloadService::DownloadEntry(const GURL& url) {
  DCHECK(reading_list_model_->loaded());
  const ReadingListEntry* entry = reading_list_model_->GetEntryByURL(url);
  if (!entry ||
      entry->DistilledState() == ReadingListEntry::DISTILLATION_ERROR ||
      entry->DistilledState() == ReadingListEntry::PROCESSED || entry->IsRead())
    return;

  if (GetApplicationContext()->GetNetworkConnectionTracker()->IsOffline()) {
    // There is no connection, save it for download only if we did not exceed
    // the maximaxum number of tries.
    if (entry->FailedDownloadCounter() < kNumberOfFailsBeforeWifiOnly)
      url_to_download_cellular_.push_back(entry->URL());
    if (entry->FailedDownloadCounter() < kNumberOfFailsBeforeStop)
      url_to_download_wifi_.push_back(entry->URL());
    return;
  }

  // There is a connection.
  if (entry->FailedDownloadCounter() < kNumberOfFailsBeforeWifiOnly) {
    // Try to download the page, whatever the connection.
    reading_list_model_->SetEntryDistilledState(entry->URL(),
                                                ReadingListEntry::PROCESSING);
    url_downloader_->DownloadOfflineURL(entry->URL());

  } else if (entry->FailedDownloadCounter() < kNumberOfFailsBeforeStop) {
    // Try to download the page only if the connection is wifi.
    auto connection_type = network::mojom::ConnectionType::CONNECTION_UNKNOWN;
    // GetConnectionType will return false if the type isn't known yet, and
    // connection_type will be unchanged, so we can ignore the return value and
    // let this treat the connection as non-wifi.
    GetApplicationContext()->GetNetworkConnectionTracker()->GetConnectionType(
        &connection_type,
        base::BindOnce(&ReadingListDownloadService::OnConnectionChanged,
                       weak_ptr_factory_.GetWeakPtr()));
    if (connection_type == network::mojom::ConnectionType::CONNECTION_WIFI) {
      // The connection is wifi, download the page.
      reading_list_model_->SetEntryDistilledState(entry->URL(),
                                                  ReadingListEntry::PROCESSING);
      url_downloader_->DownloadOfflineURL(entry->URL());

    } else {
      // The connection is not wifi, save it for download when the connection
      // changes to wifi.
      url_to_download_wifi_.push_back(entry->URL());
    }
  }
}

void ReadingListDownloadService::RemoveDownloadedEntry(const GURL& url) {
  DCHECK(reading_list_model_->loaded());
  url_downloader_->RemoveOfflineURL(url);
}

void ReadingListDownloadService::OnDownloadEnd(
    const GURL& url,
    const GURL& distilled_url,
    URLDownloader::SuccessState success,
    const base::FilePath& distilled_path,
    int64_t size,
    const std::string& title) {
  DCHECK(reading_list_model_->loaded());
  URLDownloader::SuccessState real_success_value = success;
  if (distilled_path.empty()) {
    real_success_value = URLDownloader::ERROR;
  }
  switch (real_success_value) {
    case URLDownloader::DOWNLOAD_SUCCESS:
    case URLDownloader::DOWNLOAD_EXISTS: {
      reading_list_model_->SetEntryDistilledInfo(
          url, distilled_path, distilled_url, size, base::Time::Now());

      std::string trimmed_title = base::CollapseWhitespaceASCII(title, false);
      if (!trimmed_title.empty())
        reading_list_model_->SetEntryTitle(url, trimmed_title);

      const ReadingListEntry* entry = reading_list_model_->GetEntryByURL(url);
      if (entry)
        UMA_HISTOGRAM_COUNTS_100("ReadingList.Download.Failures",
                                 entry->FailedDownloadCounter());
      UMA_HISTOGRAM_ENUMERATION("ReadingList.Download.Status", SUCCESS,
                                STATUS_MAX);
      break;
    }
    case URLDownloader::ERROR: {
      const ReadingListEntry* entry = reading_list_model_->GetEntryByURL(url);
      // Add this failure to the total failure count.
      if (entry &&
          entry->FailedDownloadCounter() + 1 < kNumberOfFailsBeforeStop) {
        reading_list_model_->SetEntryDistilledState(
            url, ReadingListEntry::WILL_RETRY);
        ScheduleDownloadEntry(url);
        UMA_HISTOGRAM_ENUMERATION("ReadingList.Download.Status", RETRY,
                                  STATUS_MAX);
      } else {
        UMA_HISTOGRAM_ENUMERATION("ReadingList.Download.Status", FAILURE,
                                  STATUS_MAX);
        reading_list_model_->SetEntryDistilledState(
            url, ReadingListEntry::DISTILLATION_ERROR);
      }
      break;
    }
  }
}

void ReadingListDownloadService::OnDeleteEnd(const GURL& url, bool success) {
  // Nothing to update as this is only called when deleting reading list entries
}

void ReadingListDownloadService::OnConnectionChanged(
    network::mojom::ConnectionType type) {
  if (type == network::mojom::ConnectionType::CONNECTION_NONE) {
    had_connection_ = false;
    return;
  }

  if (!had_connection_) {
    had_connection_ = true;
    for (auto& url : url_to_download_cellular_) {
      ScheduleDownloadEntry(url);
    }
  }
  if (type == network::mojom::ConnectionType::CONNECTION_WIFI) {
    for (auto& url : url_to_download_wifi_) {
      ScheduleDownloadEntry(url);
    }
  }
}
