// 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 <stdint.h>

#include <vector>

#include "base/logging.h"
#include "base/macros.h"
#include "base/stl_util.h"
#include "build/build_config.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_t received_bytes = 0;
  int64_t 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
