// 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 "chrome/browser/download/download_status_updater.h"

#include <vector>

#include "base/logging.h"
#include "base/stl_util.h"

#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
#include "ui/views/linux_ui/linux_ui.h"
#endif

namespace {

// DownloadStatusUpdater::UpdateAppIconDownloadProgress() expects to only be
// called once when a DownloadItem completes, then not again (except perhaps
// until it is resumed). The existence of WasInProgressData is effectively a
// boolean that indicates whether that final UpdateAppIconDownloadProgress()
// call has been made for a given DownloadItem. It is expected that there will
// be many more non-in-progress downloads than in-progress downloads, so
// WasInProgressData is set for in-progress downloads and cleared from
// non-in-progress downloads instead of the other way around in order to save
// memory.
class WasInProgressData : public base::SupportsUserData::Data {
 public:
  static bool Get(content::DownloadItem* item) {
    return item->GetUserData(kKey) != NULL;
  }

  static void Clear(content::DownloadItem* item) {
    item->RemoveUserData(kKey);
  }

  explicit WasInProgressData(content::DownloadItem* item) {
    item->SetUserData(kKey, this);
  }

 private:
  static const char kKey[];
  DISALLOW_COPY_AND_ASSIGN(WasInProgressData);
};

const char WasInProgressData::kKey[] =
  "DownloadItem DownloadStatusUpdater WasInProgressData";

}  // anonymous namespace

DownloadStatusUpdater::DownloadStatusUpdater() {
}

DownloadStatusUpdater::~DownloadStatusUpdater() {
  STLDeleteElements(&notifiers_);
}

bool DownloadStatusUpdater::GetProgress(float* progress,
                                        int* download_count) const {
  *progress = 0;
  *download_count = 0;
  bool progress_certain = true;
  int64 received_bytes = 0;
  int64 total_bytes = 0;

  for (std::vector<AllDownloadItemNotifier*>::const_iterator it =
       notifiers_.begin(); it != notifiers_.end(); ++it) {
    if ((*it)->GetManager()) {
      content::DownloadManager::DownloadVector items;
      (*it)->GetManager()->GetAllDownloads(&items);
      for (content::DownloadManager::DownloadVector::const_iterator it =
          items.begin(); it != items.end(); ++it) {
        if ((*it)->GetState() == content::DownloadItem::IN_PROGRESS) {
          ++*download_count;
          if ((*it)->GetTotalBytes() <= 0) {
            // There may or may not be more data coming down this pipe.
            progress_certain = false;
          } else {
            received_bytes += (*it)->GetReceivedBytes();
            total_bytes += (*it)->GetTotalBytes();
          }
        }
      }
    }
  }

  if (total_bytes > 0)
    *progress = static_cast<float>(received_bytes) / total_bytes;
  return progress_certain;
}

void DownloadStatusUpdater::AddManager(content::DownloadManager* manager) {
  notifiers_.push_back(new AllDownloadItemNotifier(manager, this));
  content::DownloadManager::DownloadVector items;
  manager->GetAllDownloads(&items);
  for (content::DownloadManager::DownloadVector::const_iterator
       it = items.begin(); it != items.end(); ++it) {
    OnDownloadCreated(manager, *it);
  }
}

void DownloadStatusUpdater::OnDownloadCreated(
    content::DownloadManager* manager, content::DownloadItem* item) {
  // Ignore downloads loaded from history, which are in a terminal state.
  // TODO(benjhayden): Use the Observer interface to distinguish between
  // historical and started downloads.
  if (item->GetState() == content::DownloadItem::IN_PROGRESS) {
    UpdateAppIconDownloadProgress(item);
    new WasInProgressData(item);
  }
  // else, the lack of WasInProgressData indicates to OnDownloadUpdated that it
  // should not call UpdateAppIconDownloadProgress().
}

void DownloadStatusUpdater::OnDownloadUpdated(
    content::DownloadManager* manager, content::DownloadItem* item) {
  if (item->GetState() == content::DownloadItem::IN_PROGRESS) {
    // If the item was interrupted/cancelled and then resumed/restarted, then
    // set WasInProgress so that UpdateAppIconDownloadProgress() will be called
    // when it completes.
    if (!WasInProgressData::Get(item))
      new WasInProgressData(item);
  } else {
    // The item is now in a terminal state. If it was already in a terminal
    // state, then do not call UpdateAppIconDownloadProgress() again. If it is
    // now transitioning to a terminal state, then clear its WasInProgressData
    // so that UpdateAppIconDownloadProgress() won't be called after this final
    // call.
    if (!WasInProgressData::Get(item))
      return;
    WasInProgressData::Clear(item);
  }
  UpdateAppIconDownloadProgress(item);
}

#if defined(OS_ANDROID) || (defined(USE_AURA) && !defined(OS_WIN))
void DownloadStatusUpdater::UpdateAppIconDownloadProgress(
    content::DownloadItem* download) {
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
  const views::LinuxUI* linux_ui = views::LinuxUI::instance();
  if (linux_ui) {
    float progress = 0;
    int download_count = 0;
    GetProgress(&progress, &download_count);
    linux_ui->SetDownloadCount(download_count);
    linux_ui->SetProgressFraction(progress);
  }
#endif
  // TODO(avi): Implement for Android?
}
#endif
