// 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/extensions/api/system_indicator/system_indicator_manager.h"

#include "base/memory/linked_ptr.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/event_router.h"
#include "chrome/browser/extensions/extension_action.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/status_icons/status_icon.h"
#include "chrome/browser/status_icons/status_icon_observer.h"
#include "chrome/browser/status_icons/status_tray.h"
#include "chrome/common/extensions/api/system_indicator.h"
#include "chrome/common/extensions/extension.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"
#include "ui/gfx/image/image.h"

namespace extensions {

namespace system_indicator = api::system_indicator;

// Observes clicks on a given status icon and forwards the event to the
// appropriate extension.  Handles icon updates, and responsible for creating
// and removing the icon from the notification area during construction and
// destruction.
class ExtensionIndicatorIcon : public StatusIconObserver,
                               public ExtensionActionIconFactory::Observer {
 public:
  static ExtensionIndicatorIcon* Create(const Extension* extension,
                                        const ExtensionAction* action,
                                        Profile* profile,
                                        StatusTray* status_tray);
  virtual ~ExtensionIndicatorIcon();

  // StatusIconObserver implementation.
  virtual void OnStatusIconClicked() OVERRIDE;

  // ExtensionActionIconFactory::Observer implementation.
  virtual void OnIconUpdated() OVERRIDE;

 private:
  ExtensionIndicatorIcon(const Extension* extension,
                         const ExtensionAction* action,
                         Profile* profile,
                         StatusTray* status_tray);

  const extensions::Extension* extension_;
  StatusTray* status_tray_;
  StatusIcon* icon_;
  Profile* profile_;
  ExtensionActionIconFactory icon_factory_;
};

ExtensionIndicatorIcon* ExtensionIndicatorIcon::Create(
    const Extension* extension,
    const ExtensionAction* action,
    Profile* profile,
    StatusTray* status_tray) {
  scoped_ptr<ExtensionIndicatorIcon> extension_icon(
      new ExtensionIndicatorIcon(extension, action, profile, status_tray));

  // Check if a status icon was successfully created.
  if (extension_icon->icon_)
    return extension_icon.release();

  // We could not create a status icon.
  return NULL;
}

ExtensionIndicatorIcon::~ExtensionIndicatorIcon() {
  if (icon_) {
    icon_->RemoveObserver(this);
    status_tray_->RemoveStatusIcon(icon_);
  }
}

void ExtensionIndicatorIcon::OnStatusIconClicked() {
  scoped_ptr<base::ListValue> params(
      api::system_indicator::OnClicked::Create());

  EventRouter* event_router =
      ExtensionSystem::Get(profile_)->event_router();
  scoped_ptr<Event> event(new Event(
      system_indicator::OnClicked::kEventName,
      params.Pass(),
      profile_));
  event_router->DispatchEventToExtension(
      extension_->id(), event.Pass());
}

void ExtensionIndicatorIcon::OnIconUpdated() {
  icon_->SetImage(
      icon_factory_.GetIcon(ExtensionAction::kDefaultTabId).AsImageSkia());
}

ExtensionIndicatorIcon::ExtensionIndicatorIcon(const Extension* extension,
                                               const ExtensionAction* action,
                                               Profile* profile,
                                               StatusTray* status_tray)
    : extension_(extension),
      status_tray_(status_tray),
      icon_(NULL),
      profile_(profile),
      icon_factory_(profile, extension, action, this) {
  // Get the icon image and tool tip for the status icon. The extension name is
  // used as the tool tip.
  gfx::ImageSkia icon_image =
      icon_factory_.GetIcon(ExtensionAction::kDefaultTabId).AsImageSkia();
  string16 tool_tip = UTF8ToUTF16(extension_->name());

  icon_ = status_tray_->CreateStatusIcon(
      StatusTray::OTHER_ICON, icon_image, tool_tip);
  if (icon_)
    icon_->AddObserver(this);
}

SystemIndicatorManager::SystemIndicatorManager(Profile* profile,
                                               StatusTray* status_tray)
    : profile_(profile), status_tray_(status_tray) {
  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
                 content::Source<Profile>(profile_->GetOriginalProfile()));
  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_SYSTEM_INDICATOR_UPDATED,
                 content::Source<Profile>(profile_->GetOriginalProfile()));
}

SystemIndicatorManager::~SystemIndicatorManager() {
  DCHECK(thread_checker_.CalledOnValidThread());
}

void SystemIndicatorManager::Shutdown() {
  DCHECK(thread_checker_.CalledOnValidThread());
}

void SystemIndicatorManager::Observe(
    int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  DCHECK(thread_checker_.CalledOnValidThread());

  switch (type) {
    case chrome::NOTIFICATION_EXTENSION_UNLOADED:
      RemoveIndicator(
          content::Details<UnloadedExtensionInfo>(details)->extension->id());
      break;
    case chrome::NOTIFICATION_EXTENSION_SYSTEM_INDICATOR_UPDATED:
      OnSystemIndicatorChanged(
          content::Details<ExtensionAction>(details).ptr());
      break;
    default:
      NOTREACHED();
      break;
  }
}

void SystemIndicatorManager::OnSystemIndicatorChanged(
    const ExtensionAction* extension_action) {
  DCHECK(thread_checker_.CalledOnValidThread());
  std::string extension_id = extension_action->extension_id();
  ExtensionService* service =
      ExtensionSystem::Get(profile_)->extension_service();

  if (extension_action->GetIsVisible(ExtensionAction::kDefaultTabId)) {
    const Extension* extension =
        service->GetExtensionById(extension_id, false);
    CreateOrUpdateIndicator(extension, extension_action);
  } else {
    RemoveIndicator(extension_id);
  }
}

bool SystemIndicatorManager::SendClickEventToExtensionForTest(
    const std::string extension_id) {

    extensions::SystemIndicatorManager::SystemIndicatorMap::iterator it =
        system_indicators_.find(extension_id);

    if (it == system_indicators_.end())
      return false;

    it->second->OnStatusIconClicked();
    return true;
}

void SystemIndicatorManager::CreateOrUpdateIndicator(
    const Extension* extension,
    const ExtensionAction* extension_action) {
  DCHECK(thread_checker_.CalledOnValidThread());
  SystemIndicatorMap::iterator it = system_indicators_.find(extension->id());
  if (it != system_indicators_.end()) {
    it->second->OnIconUpdated();
    return;
  }

  ExtensionIndicatorIcon* extension_icon = ExtensionIndicatorIcon::Create(
      extension, extension_action, profile_, status_tray_);
  if (extension_icon)
    system_indicators_[extension->id()] = make_linked_ptr(extension_icon);
}

void SystemIndicatorManager::RemoveIndicator(const std::string& extension_id) {
  DCHECK(thread_checker_.CalledOnValidThread());
  system_indicators_.erase(extension_id);
}

}  // namespace extensions
