// 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/ui/views/script_bubble_view.h"

#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/extensions/image_loader.h"
#include "chrome/browser/extensions/script_bubble_controller.h"
#include "chrome/browser/extensions/tab_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/manifest_handlers/icons_handler.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/page_navigator.h"
#include "content/public/browser/web_contents.h"
#include "extensions/common/extension_resource.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/link.h"
#include "ui/views/layout/grid_layout.h"
#include "ui/views/widget/widget.h"

using content::OpenURLParams;
using content::Referrer;
using content::WebContents;
using extensions::Extension;
using extensions::ExtensionSystem;
using extensions::ScriptBubbleController;

namespace {

// Layout constants.
const int kInsetTop = 7;
const int kInsetLeft = 14;
const int kInsetBottom = 11;
const int kPaddingBelowHeadline = 12;
const int kPaddingRightOfIcon = 8;
const int kPaddingBetweenRows = 13;

}  // namespace

////////////////////////////////////////////////////////////////////////////////
// ScriptBubbleView

ScriptBubbleView::ScriptEntry::ScriptEntry()
    : extension_imageview(NULL) {}

ScriptBubbleView::ScriptBubbleView(views::View* anchor_view,
                                   WebContents* web_contents)
    : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_LEFT),
      height_(0),
      web_contents_(web_contents) {
  // Compensate for built-in vertical padding in the anchor view's image.
  set_anchor_view_insets(gfx::Insets(5, 0, 5, 0));

  extensions::ScriptBubbleController* script_bubble_controller =
      GetScriptBubbleController();
  const std::set<std::string>& extensions_running_scripts =
      script_bubble_controller->extensions_running_scripts();
  Profile* profile = Profile::FromBrowserContext(
      web_contents_->GetBrowserContext());
  ExtensionService* extension_service =
      ExtensionSystem::Get(profile)->extension_service();

  size_t i = 0;
  for (std::set<std::string>::const_iterator iter =
       extensions_running_scripts.begin();
       iter != extensions_running_scripts.end(); ++iter, ++i) {
    // We specify |true| to get disabled extensions as well, since content
    // scripts survive their extensions being disabled.
    const Extension* extension =
        extension_service->GetExtensionById(*iter, true);
    ScriptEntry entry;
    entry.extension_id = *iter;
    entry.extension_name = UTF8ToUTF16(extension->name());
    entries_.push_back(entry);

    int size = extension_misc::EXTENSION_ICON_BITTY;
    extensions::ExtensionResource image =
        extensions::IconsInfo::GetIconResource(extension,
                                               size,
                                               ExtensionIconSet::MATCH_BIGGER);
    extensions::ImageLoader::Get(profile)->LoadImageAsync(
        extension, image, gfx::Size(size, size),
        base::Bind(&ScriptBubbleView::OnImageLoaded, AsWeakPtr(), i));
  }
}

ScriptBubbleView::~ScriptBubbleView() {
}

gfx::Size ScriptBubbleView::GetPreferredSize() {
  gfx::Size size(views::Widget::GetLocalizedContentsSize(
      IDS_SCRIPTBUBBLE_WIDTH_CHARS,
      IDS_SCRIPTBUBBLE_HEIGHT_LINES));
  size.set_height(std::max(size.height(), height_));
  return size;
}

void ScriptBubbleView::LinkClicked(views::Link* source, int event_flags) {
  std::string link(chrome::kChromeUIExtensionsURL);
  link += std::string("?id=") +
          entries_[source->id()].extension_id;
  web_contents_->OpenURL(OpenURLParams(GURL(link),
                                       Referrer(),
                                       NEW_FOREGROUND_TAB,
                                       content::PAGE_TRANSITION_LINK,
                                       false));
}

void ScriptBubbleView::Init() {
  height_ = 0;

  views::GridLayout* layout = new views::GridLayout(this);
  SetLayoutManager(layout);
  layout->SetInsets(kInsetTop, kInsetLeft, 0, 0);
  height_ = kInsetTop + kInsetBottom;

  // Add a column for the heading (one large text column).
  views::ColumnSet* columns = layout->AddColumnSet(0);
  columns->AddColumn(views::GridLayout::LEADING,   // Horizontal resize.
                     views::GridLayout::FILL,      // Vertical resize.
                     1,                            // Resize weight.
                     views::GridLayout::USE_PREF,  // Size type.
                     0,                            // Ignored for USE_PREF.
                     0);                           // Minimum size.

  // Add a column set for the extension image plus name.
  columns = layout->AddColumnSet(1);
  columns->AddColumn(views::GridLayout::LEADING,   // Horizontal resize.
                     views::GridLayout::FILL,      // Vertical resize.
                     0,                            // Resize weight.
                     views::GridLayout::USE_PREF,  // Size type.
                     0,                            // Ignored for USE_PREF.
                     0);                           // Minimum size.

  columns->AddPaddingColumn(0,                     // resize_percent.
                            kPaddingRightOfIcon);  // width.

  columns->AddColumn(views::GridLayout::LEADING,   // Horizontal resize.
                     views::GridLayout::FILL,      // Vertical resize.
                     1,                            // Resize weight.
                     views::GridLayout::USE_PREF,  // Size type.
                     0,                            // Ignored for USE_PREF.
                     0);                           // Minimum size.

  layout->StartRow(0, 0);
  views::Label* heading = new views::Label(
      l10n_util::GetStringUTF16(IDS_SCRIPT_BUBBLE_HEADLINE));
  layout->AddView(heading);
  height_ += heading->GetPreferredSize().height();

  layout->AddPaddingRow(0, kPaddingBelowHeadline);
  height_ += kPaddingBelowHeadline;

  for (size_t i = 0; i < entries_.size(); ++i) {
    layout->StartRow(0, 1);

    views::ImageView* image_view = new views::ImageView();
    entries_[i].extension_imageview = image_view;
    image_view->SetImageSize(gfx::Size(16, 16));
    image_view->SetImage(
        extensions::IconsInfo::GetDefaultExtensionIcon());
    layout->AddView(image_view);

    views::Link* link = new views::Link(entries_[i].extension_name);
    link->set_id(i);
    link->set_listener(this);
    layout->AddView(link);

    height_ += std::max(image_view->GetPreferredSize().height(),
                        link->GetPreferredSize().height());

    if (i + 1 < entries_.size()) {
      layout->AddPaddingRow(0, kPaddingBetweenRows);
      height_ += kPaddingBetweenRows;
    }
  }

  layout->Layout(this);
}

void ScriptBubbleView::OnImageLoaded(size_t index,
                                     const gfx::Image& image) {
  if (!image.IsEmpty()) {
    const gfx::ImageSkia* image_skia = image.ToImageSkia();
    entries_[index].extension_imageview->SetImage(image_skia);
  }
}

ScriptBubbleController* ScriptBubbleView::GetScriptBubbleController() {
  extensions::TabHelper* extensions_tab_helper =
      extensions::TabHelper::FromWebContents(web_contents_);
  return extensions_tab_helper->script_bubble_controller();
}
