// 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 <string>
#include <vector>

#include "ash/session/session_state_delegate.h"
#include "ash/shell.h"
#include "ash/shell/example_factory.h"
#include "ash/shell/toplevel_window.h"
#include "ash/shell_delegate.h"
#include "base/basictypes.h"
#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/i18n/case_conversion.h"
#include "base/i18n/string_search.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/app_list/app_list_item.h"
#include "ui/app_list/app_list_item_list.h"
#include "ui/app_list/app_list_model.h"
#include "ui/app_list/app_list_view_delegate.h"
#include "ui/app_list/search_box_model.h"
#include "ui/app_list/search_result.h"
#include "ui/app_list/speech_ui_model.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/font_list.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/views/examples/examples_window_with_content.h"

namespace ash {
namespace shell {

namespace {

// WindowTypeShelfItem is an app item of app list. It carries a window
// launch type and launches corresponding example window when activated.
class WindowTypeShelfItem : public app_list::AppListItem {
 public:
  enum Type {
    TOPLEVEL_WINDOW = 0,
    NON_RESIZABLE_WINDOW,
    LOCK_SCREEN,
    WIDGETS_WINDOW,
    EXAMPLES_WINDOW,
    LAST_TYPE,
  };

  explicit WindowTypeShelfItem(const std::string& id, Type type)
      : app_list::AppListItem(id),
        type_(type) {
    std::string title(GetTitle(type));
    SetIcon(GetIcon(type), false);
    SetName(title);
  }

  static gfx::ImageSkia GetIcon(Type type) {
    static const SkColor kColors[] = {
        SK_ColorRED,
        SK_ColorGREEN,
        SK_ColorBLUE,
        SK_ColorYELLOW,
        SK_ColorCYAN,
    };

    const int kIconSize = 128;
    SkBitmap icon;
    icon.allocN32Pixels(kIconSize, kIconSize);
    icon.eraseColor(kColors[static_cast<int>(type) % arraysize(kColors)]);
    return gfx::ImageSkia::CreateFrom1xBitmap(icon);
  }

  // The text below is not localized as this is an example code.
  static std::string GetTitle(Type type) {
    switch (type) {
      case TOPLEVEL_WINDOW:
        return "Create Window";
      case NON_RESIZABLE_WINDOW:
        return "Create Non-Resizable Window";
      case LOCK_SCREEN:
        return "Lock Screen";
      case WIDGETS_WINDOW:
        return "Show Example Widgets";
      case EXAMPLES_WINDOW:
        return "Open Views Examples Window";
      default:
        return "Unknown window type.";
    }
  }

  // The text below is not localized as this is an example code.
  static std::string GetDetails(Type type) {
    // Assigns details only to some types so that we see both one-line
    // and two-line results.
    switch (type) {
      case WIDGETS_WINDOW:
        return "Creates a window to show example widgets";
      case EXAMPLES_WINDOW:
        return "Creates a window to show views example.";
      default:
        return std::string();
    }
  }

  static void ActivateItem(Type type, int event_flags) {
     switch (type) {
      case TOPLEVEL_WINDOW: {
        ToplevelWindow::CreateParams params;
        params.can_resize = true;
        ToplevelWindow::CreateToplevelWindow(params);
        break;
      }
      case NON_RESIZABLE_WINDOW: {
        ToplevelWindow::CreateToplevelWindow(ToplevelWindow::CreateParams());
        break;
      }
      case LOCK_SCREEN: {
        Shell::GetInstance()->session_state_delegate()->LockScreen();
        break;
      }
      case WIDGETS_WINDOW: {
        CreateWidgetsWindow();
        break;
      }
      case EXAMPLES_WINDOW: {
        views::examples::ShowExamplesWindowWithContent(
            views::examples::DO_NOTHING_ON_CLOSE,
            Shell::GetInstance()->delegate()->GetActiveBrowserContext(),
            NULL);
        break;
      }
      default:
        break;
    }
  }

  // AppListItem
  virtual void Activate(int event_flags) OVERRIDE {
    ActivateItem(type_, event_flags);
  }

 private:
  Type type_;

  DISALLOW_COPY_AND_ASSIGN(WindowTypeShelfItem);
};

// ExampleSearchResult is an app list search result. It provides what icon to
// show, what should title and details text look like. It also carries the
// matching window launch type so that AppListViewDelegate knows how to open
// it.
class ExampleSearchResult : public app_list::SearchResult {
 public:
  ExampleSearchResult(WindowTypeShelfItem::Type type,
                      const base::string16& query)
      : type_(type) {
    SetIcon(WindowTypeShelfItem::GetIcon(type_));

    base::string16 title =
        base::UTF8ToUTF16(WindowTypeShelfItem::GetTitle(type_));
    set_title(title);

    Tags title_tags;
    const size_t match_len = query.length();

    // Highlight matching parts in title with bold.
    // Note the following is not a proper way to handle i18n string.
    title = base::i18n::ToLower(title);
    size_t match_start = title.find(query);
    while (match_start != base::string16::npos) {
      title_tags.push_back(Tag(Tag::MATCH,
                               match_start,
                               match_start + match_len));
      match_start = title.find(query, match_start + match_len);
    }
    set_title_tags(title_tags);

    base::string16 details =
        base::UTF8ToUTF16(WindowTypeShelfItem::GetDetails(type_));
    set_details(details);
    Tags details_tags;
    details_tags.push_back(Tag(Tag::DIM, 0, details.length()));
    set_details_tags(details_tags);
  }

  WindowTypeShelfItem::Type type() const { return type_; }

 private:
  WindowTypeShelfItem::Type type_;

  DISALLOW_COPY_AND_ASSIGN(ExampleSearchResult);
};

class ExampleAppListViewDelegate : public app_list::AppListViewDelegate {
 public:
  ExampleAppListViewDelegate()
      : model_(new app_list::AppListModel),
        speech_ui_(app_list::SPEECH_RECOGNITION_OFF) {
    PopulateApps();
    DecorateSearchBox(model_->search_box());
  }

 private:
  void PopulateApps() {
    for (int i = 0; i < static_cast<int>(WindowTypeShelfItem::LAST_TYPE); ++i) {
      WindowTypeShelfItem::Type type =
          static_cast<WindowTypeShelfItem::Type>(i);
      std::string id = base::StringPrintf("%d", i);
      scoped_ptr<WindowTypeShelfItem> shelf_item(
          new WindowTypeShelfItem(id, type));
      model_->AddItem(shelf_item.PassAs<app_list::AppListItem>());
    }
  }

  gfx::ImageSkia CreateSearchBoxIcon() {
    const base::string16 icon_text = base::ASCIIToUTF16("ash");
    const gfx::Size icon_size(32, 32);

    gfx::Canvas canvas(icon_size, 1.0f, false /* is_opaque */);
    canvas.DrawStringRectWithFlags(
        icon_text,
        gfx::FontList(),
        SK_ColorBLACK,
        gfx::Rect(icon_size),
        gfx::Canvas::TEXT_ALIGN_CENTER | gfx::Canvas::NO_SUBPIXEL_RENDERING);

    return gfx::ImageSkia(canvas.ExtractImageRep());
  }

  void DecorateSearchBox(app_list::SearchBoxModel* search_box_model) {
    search_box_model->SetIcon(CreateSearchBoxIcon());
    search_box_model->SetHintText(base::ASCIIToUTF16("Type to search..."));
  }

  // Overridden from app_list::AppListViewDelegate:
  virtual bool ForceNativeDesktop() const OVERRIDE {
    return false;
  }

  virtual void SetProfileByPath(const base::FilePath& profile_path) OVERRIDE {
    // Nothing needs to be done.
  }

  virtual const Users& GetUsers() const OVERRIDE {
    return users_;
  }

  virtual bool ShouldCenterWindow() const OVERRIDE {
    return false;
  }

  virtual app_list::AppListModel* GetModel() OVERRIDE { return model_.get(); }

  virtual app_list::SpeechUIModel* GetSpeechUI() OVERRIDE {
    return &speech_ui_;
  }

  virtual void GetShortcutPathForApp(
      const std::string& app_id,
      const base::Callback<void(const base::FilePath&)>& callback) OVERRIDE {
    callback.Run(base::FilePath());
  }

  virtual void OpenSearchResult(app_list::SearchResult* result,
                                bool auto_launch,
                                int event_flags) OVERRIDE {
    const ExampleSearchResult* example_result =
        static_cast<const ExampleSearchResult*>(result);
    WindowTypeShelfItem::ActivateItem(example_result->type(), event_flags);
  }

  virtual void InvokeSearchResultAction(app_list::SearchResult* result,
                                        int action_index,
                                        int event_flags) OVERRIDE {
    NOTIMPLEMENTED();
  }

  virtual base::TimeDelta GetAutoLaunchTimeout() OVERRIDE {
    return base::TimeDelta();
  }

  virtual void AutoLaunchCanceled() OVERRIDE {
  }

  virtual void StartSearch() OVERRIDE {
    base::string16 query;
    base::TrimWhitespace(model_->search_box()->text(), base::TRIM_ALL, &query);
    query = base::i18n::ToLower(query);

    model_->results()->DeleteAll();
    if (query.empty())
      return;

    for (int i = 0; i < static_cast<int>(WindowTypeShelfItem::LAST_TYPE); ++i) {
      WindowTypeShelfItem::Type type =
          static_cast<WindowTypeShelfItem::Type>(i);

      base::string16 title =
          base::UTF8ToUTF16(WindowTypeShelfItem::GetTitle(type));
      if (base::i18n::StringSearchIgnoringCaseAndAccents(
              query, title, NULL, NULL)) {
        model_->results()->Add(new ExampleSearchResult(type, query));
      }
    }
  }

  virtual void StopSearch() OVERRIDE {
    // Nothing needs to be done.
  }

  virtual void ViewInitialized() OVERRIDE {
    // Nothing needs to be done.
  }

  virtual void Dismiss() OVERRIDE {
    DCHECK(ash::Shell::HasInstance());
    Shell::GetInstance()->DismissAppList();
  }

  virtual void ViewClosing() OVERRIDE {
    // Nothing needs to be done.
  }

  virtual gfx::ImageSkia GetWindowIcon() OVERRIDE {
    return gfx::ImageSkia();
  }

  virtual void OpenSettings() OVERRIDE {
    // Nothing needs to be done.
  }

  virtual void OpenHelp() OVERRIDE {
    // Nothing needs to be done.
  }

  virtual void OpenFeedback() OVERRIDE {
    // Nothing needs to be done.
  }

  virtual void ToggleSpeechRecognition() OVERRIDE {
    NOTIMPLEMENTED();
  }

  virtual void ShowForProfileByPath(
      const base::FilePath& profile_path) OVERRIDE {
    // Nothing needs to be done.
  }

  virtual views::View* CreateStartPageWebView(const gfx::Size& size) OVERRIDE {
    return NULL;
  }

  virtual std::vector<views::View*> CreateCustomPageWebViews(
      const gfx::Size& size) OVERRIDE {
    return std::vector<views::View*>();
  }

  virtual bool IsSpeechRecognitionEnabled() OVERRIDE {
    return false;
  }

  scoped_ptr<app_list::AppListModel> model_;
  app_list::SpeechUIModel speech_ui_;
  Users users_;

  DISALLOW_COPY_AND_ASSIGN(ExampleAppListViewDelegate);
};

}  // namespace

app_list::AppListViewDelegate* CreateAppListViewDelegate() {
  return new ExampleAppListViewDelegate;
}

}  // namespace shell
}  // namespace ash
