// Copyright (c) 2013 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 "ui/message_center/views/message_popup_collection.h"

#include <set>

#include "base/bind.h"
#include "base/i18n/rtl.h"
#include "base/logging.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "ui/accessibility/ax_enums.h"
#include "ui/gfx/animation/animation_delegate.h"
#include "ui/gfx/animation/slide_animation.h"
#include "ui/gfx/screen.h"
#include "ui/message_center/message_center.h"
#include "ui/message_center/message_center_style.h"
#include "ui/message_center/message_center_tray.h"
#include "ui/message_center/notification.h"
#include "ui/message_center/notification_list.h"
#include "ui/message_center/views/message_view_context_menu_controller.h"
#include "ui/message_center/views/notification_view.h"
#include "ui/message_center/views/popup_alignment_delegate.h"
#include "ui/message_center/views/toast_contents_view.h"
#include "ui/views/background.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/view.h"
#include "ui/views/views_delegate.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"

namespace message_center {
namespace {

// Timeout between the last user-initiated close of the toast and the moment
// when normal layout/update of the toast stack continues. If the last toast was
// just closed, the timeout is shorter.
const int kMouseExitedDeferTimeoutMs = 200;

// The margin between messages (and between the anchor unless
// first_item_has_no_margin was specified).
const int kToastMarginY = kMarginBetweenItems;

}  // namespace.

MessagePopupCollection::MessagePopupCollection(
    gfx::NativeView parent,
    MessageCenter* message_center,
    MessageCenterTray* tray,
    PopupAlignmentDelegate* alignment_delegate)
    : parent_(parent),
      message_center_(message_center),
      tray_(tray),
      alignment_delegate_(alignment_delegate),
      defer_counter_(0),
      latest_toast_entered_(NULL),
      user_is_closing_toasts_by_clicking_(false),
      context_menu_controller_(new MessageViewContextMenuController(this)),
      weak_factory_(this) {
  DCHECK(message_center_);
  defer_timer_.reset(new base::OneShotTimer<MessagePopupCollection>);
  message_center_->AddObserver(this);
  alignment_delegate_->set_collection(this);
}

MessagePopupCollection::~MessagePopupCollection() {
  weak_factory_.InvalidateWeakPtrs();

  message_center_->RemoveObserver(this);

  CloseAllWidgets();
}

void MessagePopupCollection::ClickOnNotification(
    const std::string& notification_id) {
  message_center_->ClickOnNotification(notification_id);
}

void MessagePopupCollection::RemoveNotification(
    const std::string& notification_id,
    bool by_user) {
  message_center_->RemoveNotification(notification_id, by_user);
}

scoped_ptr<ui::MenuModel> MessagePopupCollection::CreateMenuModel(
    const NotifierId& notifier_id,
    const base::string16& display_source) {
  return tray_->CreateNotificationMenuModel(notifier_id, display_source);
}

bool MessagePopupCollection::HasClickedListener(
    const std::string& notification_id) {
  return message_center_->HasClickedListener(notification_id);
}

void MessagePopupCollection::ClickOnNotificationButton(
    const std::string& notification_id,
    int button_index) {
  message_center_->ClickOnNotificationButton(notification_id, button_index);
}

void MessagePopupCollection::MarkAllPopupsShown() {
  std::set<std::string> closed_ids = CloseAllWidgets();
  for (std::set<std::string>::iterator iter = closed_ids.begin();
       iter != closed_ids.end(); iter++) {
    message_center_->MarkSinglePopupAsShown(*iter, false);
  }
}

void MessagePopupCollection::UpdateWidgets() {
  NotificationList::PopupNotifications popups =
      message_center_->GetPopupNotifications();

  if (popups.empty()) {
    CloseAllWidgets();
    return;
  }

  bool top_down = alignment_delegate_->IsTopDown();
  int base = GetBaseLine(toasts_.empty() ? NULL : toasts_.back());

  // Iterate in the reverse order to keep the oldest toasts on screen. Newer
  // items may be ignored if there are no room to place them.
  for (NotificationList::PopupNotifications::const_reverse_iterator iter =
           popups.rbegin(); iter != popups.rend(); ++iter) {
    if (FindToast((*iter)->id()))
      continue;

    NotificationView* view =
        NotificationView::Create(NULL,
                                 *(*iter),
                                 true); // Create top-level notification.
    view->set_context_menu_controller(context_menu_controller_.get());
    int view_height = ToastContentsView::GetToastSizeForView(view).height();
    int height_available =
        top_down ? alignment_delegate_->GetWorkAreaBottom() - base : base;

    if (height_available - view_height - kToastMarginY < 0) {
      delete view;
      break;
    }

    ToastContentsView* toast =
        new ToastContentsView((*iter)->id(), weak_factory_.GetWeakPtr());
    // There will be no contents already since this is a new ToastContentsView.
    toast->SetContents(view, /*a11y_feedback_for_updates=*/false);
    toasts_.push_back(toast);
    view->set_controller(toast);

    gfx::Size preferred_size = toast->GetPreferredSize();
    gfx::Point origin(
        alignment_delegate_->GetToastOriginX(gfx::Rect(preferred_size)), base);
    // The toast slides in from the edge of the screen horizontally.
    if (alignment_delegate_->IsFromLeft())
      origin.set_x(origin.x() - preferred_size.width());
    else
      origin.set_x(origin.x() + preferred_size.width());
    if (top_down)
      origin.set_y(origin.y() + view_height);

    toast->RevealWithAnimation(origin);

    // Shift the base line to be a few pixels above the last added toast or (few
    // pixels below last added toast if top-aligned).
    if (top_down)
      base += view_height + kToastMarginY;
    else
      base -= view_height + kToastMarginY;

    if (views::ViewsDelegate::views_delegate) {
      views::ViewsDelegate::views_delegate->NotifyAccessibilityEvent(
          toast, ui::AX_EVENT_ALERT);
    }

    message_center_->DisplayedNotification(
        (*iter)->id(), message_center::DISPLAY_SOURCE_POPUP);
  }
}

void MessagePopupCollection::OnMouseEntered(ToastContentsView* toast_entered) {
  // Sometimes we can get two MouseEntered/MouseExited in a row when animating
  // toasts.  So we need to keep track of which one is the currently active one.
  latest_toast_entered_ = toast_entered;

  message_center_->PausePopupTimers();

  if (user_is_closing_toasts_by_clicking_)
    defer_timer_->Stop();
}

void MessagePopupCollection::OnMouseExited(ToastContentsView* toast_exited) {
  // If we're exiting a toast after entering a different toast, then ignore
  // this mouse event.
  if (toast_exited != latest_toast_entered_)
    return;
  latest_toast_entered_ = NULL;

  if (user_is_closing_toasts_by_clicking_) {
    defer_timer_->Start(
        FROM_HERE,
        base::TimeDelta::FromMilliseconds(kMouseExitedDeferTimeoutMs),
        this,
        &MessagePopupCollection::OnDeferTimerExpired);
  } else {
    message_center_->RestartPopupTimers();
  }
}

std::set<std::string> MessagePopupCollection::CloseAllWidgets() {
  std::set<std::string> closed_toast_ids;

  while (!toasts_.empty()) {
    ToastContentsView* toast = toasts_.front();
    toasts_.pop_front();
    closed_toast_ids.insert(toast->id());

    OnMouseExited(toast);

    // CloseWithAnimation will cause the toast to forget about |this| so it is
    // required when we forget a toast.
    toast->CloseWithAnimation();
  }

  return closed_toast_ids;
}

void MessagePopupCollection::ForgetToast(ToastContentsView* toast) {
  toasts_.remove(toast);
  OnMouseExited(toast);
}

void MessagePopupCollection::RemoveToast(ToastContentsView* toast,
                                         bool mark_as_shown) {
  ForgetToast(toast);

  toast->CloseWithAnimation();

  if (mark_as_shown)
    message_center_->MarkSinglePopupAsShown(toast->id(), false);
}

void MessagePopupCollection::RepositionWidgets() {
  bool top_down = alignment_delegate_->IsTopDown();
  int base = GetBaseLine(NULL);  // We don't want to position relative to last
                                 // toast - we want re-position.

  for (Toasts::const_iterator iter = toasts_.begin(); iter != toasts_.end();) {
    Toasts::const_iterator curr = iter++;
    gfx::Rect bounds((*curr)->bounds());
    bounds.set_x(alignment_delegate_->GetToastOriginX(bounds));
    bounds.set_y(top_down ? base : base - bounds.height());

    // The notification may scrolls the boundary of the screen due to image
    // load and such notifications should disappear. Do not call
    // CloseWithAnimation, we don't want to show the closing animation, and we
    // don't want to mark such notifications as shown. See crbug.com/233424
    if ((top_down ? alignment_delegate_->GetWorkAreaBottom() - bounds.bottom()
                  : bounds.y()) >= 0)
      (*curr)->SetBoundsWithAnimation(bounds);
    else
      RemoveToast(*curr, /*mark_as_shown=*/false);

    // Shift the base line to be a few pixels above the last added toast or (few
    // pixels below last added toast if top-aligned).
    if (top_down)
      base += bounds.height() + kToastMarginY;
    else
      base -= bounds.height() + kToastMarginY;
  }
}

void MessagePopupCollection::RepositionWidgetsWithTarget() {
  if (toasts_.empty())
    return;

  bool top_down = alignment_delegate_->IsTopDown();

  // Nothing to do if there are no widgets above target if bottom-aligned or no
  // widgets below target if top-aligned.
  if (top_down ? toasts_.back()->origin().y() < target_top_edge_
               : toasts_.back()->origin().y() > target_top_edge_)
    return;

  Toasts::reverse_iterator iter = toasts_.rbegin();
  for (; iter != toasts_.rend(); ++iter) {
    // We only reposition widgets above target if bottom-aligned or widgets
    // below target if top-aligned.
    if (top_down ? (*iter)->origin().y() < target_top_edge_
                 : (*iter)->origin().y() > target_top_edge_)
      break;
  }
  --iter;

  // Slide length is the number of pixels the widgets should move so that their
  // bottom edge (top-edge if top-aligned) touches the target.
  int slide_length = std::abs(target_top_edge_ - (*iter)->origin().y());
  for (;; --iter) {
    gfx::Rect bounds((*iter)->bounds());

    // If top-aligned, shift widgets upwards by slide_length. If bottom-aligned,
    // shift them downwards by slide_length.
    if (top_down)
      bounds.set_y(bounds.y() - slide_length);
    else
      bounds.set_y(bounds.y() + slide_length);
    (*iter)->SetBoundsWithAnimation(bounds);

    if (iter == toasts_.rbegin())
      break;
  }
}

int MessagePopupCollection::GetBaseLine(ToastContentsView* last_toast) const {
  if (!last_toast) {
    return alignment_delegate_->GetBaseLine();
  } else if (alignment_delegate_->IsTopDown()) {
    return toasts_.back()->bounds().bottom() + kToastMarginY;
  } else {
    return toasts_.back()->origin().y() - kToastMarginY;
  }
}

void MessagePopupCollection::OnNotificationAdded(
    const std::string& notification_id) {
  DoUpdateIfPossible();
}

void MessagePopupCollection::OnNotificationRemoved(
    const std::string& notification_id,
    bool by_user) {
  // Find a toast.
  Toasts::const_iterator iter = toasts_.begin();
  for (; iter != toasts_.end(); ++iter) {
    if ((*iter)->id() == notification_id)
      break;
  }
  if (iter == toasts_.end())
    return;

  target_top_edge_ = (*iter)->bounds().y();
  if (by_user && !user_is_closing_toasts_by_clicking_) {
    // [Re] start a timeout after which the toasts re-position to their
    // normal locations after tracking the mouse pointer for easy deletion.
    // This provides a period of time when toasts are easy to remove because
    // they re-position themselves to have Close button right under the mouse
    // pointer. If the user continue to remove the toasts, the delay is reset.
    // Once user stopped removing the toasts, the toasts re-populate/rearrange
    // after the specified delay.
    user_is_closing_toasts_by_clicking_ = true;
    IncrementDeferCounter();
  }

  // CloseWithAnimation ultimately causes a call to RemoveToast, which calls
  // OnMouseExited.  This means that |user_is_closing_toasts_by_clicking_| must
  // have been set before this call, otherwise it will remain true even after
  // the toast is closed, since the defer timer won't be started.
  RemoveToast(*iter, /*mark_as_shown=*/true);

  if (by_user)
    RepositionWidgetsWithTarget();
}

void MessagePopupCollection::OnDeferTimerExpired() {
  user_is_closing_toasts_by_clicking_ = false;
  DecrementDeferCounter();

  message_center_->RestartPopupTimers();
}

void MessagePopupCollection::OnNotificationUpdated(
    const std::string& notification_id) {
  // Find a toast.
  Toasts::const_iterator toast_iter = toasts_.begin();
  for (; toast_iter != toasts_.end(); ++toast_iter) {
    if ((*toast_iter)->id() == notification_id)
      break;
  }
  if (toast_iter == toasts_.end())
    return;

  NotificationList::PopupNotifications notifications =
      message_center_->GetPopupNotifications();
  bool updated = false;

  for (NotificationList::PopupNotifications::iterator iter =
           notifications.begin(); iter != notifications.end(); ++iter) {
    Notification* notification = *iter;
    DCHECK(notification);
    ToastContentsView* toast_contents_view = *toast_iter;
    DCHECK(toast_contents_view);

    if (notification->id() != notification_id)
      continue;

    const RichNotificationData& optional_fields =
        notification->rich_notification_data();
    bool a11y_feedback_for_updates =
        optional_fields.should_make_spoken_feedback_for_popup_updates;

    toast_contents_view->UpdateContents(*notification,
                                        a11y_feedback_for_updates);

    updated = true;
  }

  // OnNotificationUpdated() can be called when a notification is excluded from
  // the popup notification list but still remains in the full notification
  // list. In that case the widget for the notification has to be closed here.
  if (!updated)
    RemoveToast(*toast_iter, /*mark_as_shown=*/true);

  if (user_is_closing_toasts_by_clicking_)
    RepositionWidgetsWithTarget();
  else
    DoUpdateIfPossible();
}

ToastContentsView* MessagePopupCollection::FindToast(
    const std::string& notification_id) const {
  for (Toasts::const_iterator iter = toasts_.begin(); iter != toasts_.end();
       ++iter) {
    if ((*iter)->id() == notification_id)
      return *iter;
  }
  return NULL;
}

void MessagePopupCollection::IncrementDeferCounter() {
  defer_counter_++;
}

void MessagePopupCollection::DecrementDeferCounter() {
  defer_counter_--;
  DCHECK(defer_counter_ >= 0);
  DoUpdateIfPossible();
}

// This is the main sequencer of tasks. It does a step, then waits for
// all started transitions to play out before doing the next step.
// First, remove all expired toasts.
// Then, reposition widgets (the reposition on close happens before all
// deferred tasks are even able to run)
// Then, see if there is vacant space for new toasts.
void MessagePopupCollection::DoUpdateIfPossible() {
  if (defer_counter_ > 0)
    return;

  RepositionWidgets();

  if (defer_counter_ > 0)
    return;

  // Reposition could create extra space which allows additional widgets.
  UpdateWidgets();

  if (defer_counter_ > 0)
    return;

  // Test support. Quit the test run loop when no more updates are deferred,
  // meaining th echeck for updates did not cause anything to change so no new
  // transition animations were started.
  if (run_loop_for_test_.get())
    run_loop_for_test_->Quit();
}

void MessagePopupCollection::OnDisplayMetricsChanged(
    const gfx::Display& display) {
  alignment_delegate_->RecomputeAlignment(display);
}

views::Widget* MessagePopupCollection::GetWidgetForTest(const std::string& id)
    const {
  for (Toasts::const_iterator iter = toasts_.begin(); iter != toasts_.end();
       ++iter) {
    if ((*iter)->id() == id)
      return (*iter)->GetWidget();
  }
  return NULL;
}

void MessagePopupCollection::CreateRunLoopForTest() {
  run_loop_for_test_.reset(new base::RunLoop());
}

void MessagePopupCollection::WaitForTest() {
  run_loop_for_test_->Run();
  run_loop_for_test_.reset();
}

gfx::Rect MessagePopupCollection::GetToastRectAt(size_t index) const {
  DCHECK(defer_counter_ == 0) << "Fetching the bounds with animations active.";
  size_t i = 0;
  for (Toasts::const_iterator iter = toasts_.begin(); iter != toasts_.end();
       ++iter) {
    if (i++ == index) {
      views::Widget* widget = (*iter)->GetWidget();
      if (widget)
        return widget->GetWindowBoundsInScreen();
      break;
    }
  }
  return gfx::Rect();
}

}  // namespace message_center
