// 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 <utility>

#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/extensions/extension_action.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 "content/public/browser/web_contents.h"
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/extension.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 std::unique_ptr<ExtensionIndicatorIcon> Create(
      const Extension* extension,
      ExtensionAction* action,
      Profile* profile,
      StatusTray* status_tray);
  ~ExtensionIndicatorIcon() override;

  // StatusIconObserver implementation.
  void OnStatusIconClicked() override;

  // ExtensionActionIconFactory::Observer implementation.
  void OnIconUpdated() override;

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

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

std::unique_ptr<ExtensionIndicatorIcon> ExtensionIndicatorIcon::Create(
    const Extension* extension,
    ExtensionAction* action,
    Profile* profile,
    StatusTray* status_tray) {
  std::unique_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;

  // We could not create a status icon.
  return std::unique_ptr<ExtensionIndicatorIcon>();
}

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

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

  EventRouter* event_router = EventRouter::Get(profile_);
  std::unique_ptr<Event> event(new Event(
      events::SYSTEM_INDICATOR_ON_CLICKED,
      system_indicator::OnClicked::kEventName, std::move(params), profile_));
  event_router->DispatchEventToExtension(extension_->id(), std::move(event));
}

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

ExtensionIndicatorIcon::ExtensionIndicatorIcon(const Extension* extension,
                                               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();
  base::string16 tool_tip = base::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),
      extension_action_observer_(this),
      extension_registry_observer_(this) {
  extension_registry_observer_.Add(ExtensionRegistry::Get(profile_));
  extension_action_observer_.Add(ExtensionActionAPI::Get(profile_));
}

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

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

void SystemIndicatorManager::OnExtensionUnloaded(
    content::BrowserContext* browser_context,
    const Extension* extension,
    UnloadedExtensionInfo::Reason reason) {
  RemoveIndicator(extension->id());
}

void SystemIndicatorManager::OnExtensionActionUpdated(
    ExtensionAction* extension_action,
    content::WebContents* web_contents,
    content::BrowserContext* browser_context) {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (profile_->GetOriginalProfile() != browser_context ||
      extension_action->action_type() != ActionInfo::TYPE_SYSTEM_INDICATOR)
    return;

  std::string extension_id = extension_action->extension_id();
  if (extension_action->GetIsVisible(ExtensionAction::kDefaultTabId)) {
    CreateOrUpdateIndicator(
        ExtensionRegistry::Get(profile_)->enabled_extensions().GetByID(
            extension_id),
        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,
    ExtensionAction* extension_action) {
  DCHECK(thread_checker_.CalledOnValidThread());
  SystemIndicatorMap::iterator it = system_indicators_.find(extension->id());
  if (it != system_indicators_.end()) {
    it->second->OnIconUpdated();
    return;
  }

  std::unique_ptr<ExtensionIndicatorIcon> extension_icon =
      ExtensionIndicatorIcon::Create(extension, extension_action, profile_,
                                     status_tray_);
  if (extension_icon)
    system_indicators_[extension->id()] = std::move(extension_icon);
}

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

}  // namespace extensions
