// 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 "ash/wm/partial_screenshot_view.h"

#include <algorithm>

#include "ash/display/mouse_cursor_event_filter.h"
#include "ash/screenshot_delegate.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "ash/wm/overlay_event_filter.h"
#include "ui/aura/client/capture_client.h"
#include "ui/aura/root_window.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/events/event.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/rect.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_observer.h"

namespace ash {

// A self-owned object to handle the cancel and the finish of current partial
// screenshot session.
class PartialScreenshotView::OverlayDelegate
    : public internal::OverlayEventFilter::Delegate,
      public views::WidgetObserver {
 public:
  OverlayDelegate() {
    Shell::GetInstance()->overlay_filter()->Activate(this);
  }

  void RegisterWidget(views::Widget* widget) {
    widgets_.push_back(widget);
    widget->AddObserver(this);
  }

  // Overridden from OverlayEventFilter::Delegate:
  virtual void Cancel() OVERRIDE {
    // Make sure the mouse_warp_mode allows warping. It can be stopped by a
    // partial screenshot view.
    internal::MouseCursorEventFilter* mouse_cursor_filter =
        Shell::GetInstance()->mouse_cursor_filter();
    mouse_cursor_filter->set_mouse_warp_mode(
        internal::MouseCursorEventFilter::WARP_ALWAYS);
    for (size_t i = 0; i < widgets_.size(); ++i)
      widgets_[i]->Close();
  }

  virtual bool IsCancelingKeyEvent(ui::KeyEvent* event) OVERRIDE {
    return event->key_code() == ui::VKEY_ESCAPE;
  }

  virtual aura::Window* GetWindow() OVERRIDE {
    // Just returns NULL because this class does not handle key events in
    // OverlayEventFilter, except for cancel keys.
    return NULL;
  }

  // Overridden from views::WidgetObserver:
  virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE {
    widget->RemoveObserver(this);
    widgets_.erase(std::remove(widgets_.begin(), widgets_.end(), widget));
    if (widgets_.empty())
      delete this;
  }

 private:
  virtual ~OverlayDelegate() {
    Shell::GetInstance()->overlay_filter()->Deactivate();
  }

  std::vector<views::Widget*> widgets_;

  DISALLOW_COPY_AND_ASSIGN(OverlayDelegate);
};

// static
std::vector<PartialScreenshotView*>
PartialScreenshotView::StartPartialScreenshot(
    ScreenshotDelegate* screenshot_delegate) {
  std::vector<PartialScreenshotView*> views;
  OverlayDelegate* overlay_delegate = new OverlayDelegate();
  Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
  for (Shell::RootWindowList::iterator it = root_windows.begin();
       it != root_windows.end(); ++it) {
    PartialScreenshotView* new_view = new PartialScreenshotView(
        overlay_delegate, screenshot_delegate);
    new_view->Init(*it);
    views.push_back(new_view);
  }
  return views;
}

PartialScreenshotView::PartialScreenshotView(
    PartialScreenshotView::OverlayDelegate* overlay_delegate,
    ScreenshotDelegate* screenshot_delegate)
    : is_dragging_(false),
      overlay_delegate_(overlay_delegate),
      screenshot_delegate_(screenshot_delegate) {
}

PartialScreenshotView::~PartialScreenshotView() {
  overlay_delegate_ = NULL;
  screenshot_delegate_ = NULL;
}

void PartialScreenshotView::Init(aura::RootWindow* root_window) {
  views::Widget* widget = new views::Widget;
  views::Widget::InitParams params(
      views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
  params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
  params.delegate = this;
  // The partial screenshot rectangle has to be at the real top of
  // the screen.
  params.parent = Shell::GetContainer(
      root_window,
      internal::kShellWindowId_OverlayContainer);

  widget->Init(params);
  widget->SetContentsView(this);
  widget->SetBounds(root_window->GetBoundsInScreen());
  widget->GetNativeView()->SetName("PartialScreenshotView");
  widget->StackAtTop();
  widget->Show();
  // Releases the mouse capture to let mouse events come to the view. This
  // will close the context menu.
  aura::client::CaptureClient* capture_client =
      aura::client::GetCaptureClient(root_window);
  if (capture_client->GetCaptureWindow())
    capture_client->ReleaseCapture(capture_client->GetCaptureWindow());

  overlay_delegate_->RegisterWidget(widget);
}

gfx::Rect PartialScreenshotView::GetScreenshotRect() const {
  int left = std::min(start_position_.x(), current_position_.x());
  int top = std::min(start_position_.y(), current_position_.y());
  int width = ::abs(start_position_.x() - current_position_.x());
  int height = ::abs(start_position_.y() - current_position_.y());
  return gfx::Rect(left, top, width, height);
}

void PartialScreenshotView::OnSelectionStarted(const gfx::Point& position) {
  start_position_ = position;
}

void PartialScreenshotView::OnSelectionChanged(const gfx::Point& position) {
  if (is_dragging_ && current_position_ == position)
    return;
  current_position_ = position;
  SchedulePaint();
  is_dragging_ = true;
}

void PartialScreenshotView::OnSelectionFinished() {
  overlay_delegate_->Cancel();
  if (!is_dragging_)
    return;

  is_dragging_ = false;
  if (screenshot_delegate_) {
    aura::RootWindow *root_window =
        GetWidget()->GetNativeWindow()->GetRootWindow();
    screenshot_delegate_->HandleTakePartialScreenshot(
        root_window,
        gfx::IntersectRects(root_window->bounds(), GetScreenshotRect()));
  }
}

gfx::NativeCursor PartialScreenshotView::GetCursor(
    const ui::MouseEvent& event) {
  // Always use "crosshair" cursor.
  return ui::kCursorCross;
}

void PartialScreenshotView::OnPaint(gfx::Canvas* canvas) {
  if (is_dragging_) {
    // Screenshot area representation: black rectangle with white
    // rectangle inside.  To avoid capturing these rectangles when mouse
    // release, they should be outside of the actual capturing area.
    gfx::Rect screenshot_rect = GetScreenshotRect();
    screenshot_rect.Inset(-1, -1, -1, -1);
    canvas->DrawRect(screenshot_rect, SK_ColorWHITE);
    screenshot_rect.Inset(-1, -1, -1, -1);
    canvas->DrawRect(screenshot_rect, SK_ColorBLACK);
  }
}

bool PartialScreenshotView::OnMousePressed(const ui::MouseEvent& event) {
  // Prevent moving across displays during drag. Capturing a screenshot across
  // the displays is not supported yet.
  // TODO(mukai): remove this restriction.
  internal::MouseCursorEventFilter* mouse_cursor_filter =
      Shell::GetInstance()->mouse_cursor_filter();
  mouse_cursor_filter->set_mouse_warp_mode(
      internal::MouseCursorEventFilter::WARP_NONE);
  OnSelectionStarted(event.location());
  return true;
}

bool PartialScreenshotView::OnMouseDragged(const ui::MouseEvent& event) {
  OnSelectionChanged(event.location());
  return true;
}

bool PartialScreenshotView::OnMouseWheel(const ui::MouseWheelEvent& event) {
  // Do nothing but do not propagate events futhermore.
  return true;
}

void PartialScreenshotView::OnMouseReleased(const ui::MouseEvent& event) {
  OnSelectionFinished();
}

void PartialScreenshotView::OnMouseCaptureLost() {
  is_dragging_ = false;
  OnSelectionFinished();
}

void PartialScreenshotView::OnGestureEvent(ui::GestureEvent* event) {
  switch(event->type()) {
    case ui::ET_GESTURE_TAP_DOWN:
      OnSelectionStarted(event->location());
      break;
    case ui::ET_GESTURE_SCROLL_UPDATE:
      OnSelectionChanged(event->location());
      break;
    case ui::ET_GESTURE_SCROLL_END:
    case ui::ET_SCROLL_FLING_START:
      OnSelectionFinished();
      break;
    default:
      break;
  }

  event->SetHandled();
}

}  // namespace ash
