// 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/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.h"
#include "ui/message_center/views/message_view_context_menu_controller.h"
#include "ui/message_center/views/message_view_factory.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(
    MessageCenter* message_center,
    MessageCenterTray* tray,
    PopupAlignmentDelegate* alignment_delegate)
    : message_center_(message_center),
      tray_(tray),
      alignment_delegate_(alignment_delegate),
      defer_counter_(0),
      latest_toast_entered_(NULL),
      user_is_closing_toasts_by_clicking_(false),
      target_top_edge_(0),
      context_menu_controller_(new MessageViewContextMenuController(this)),
      weak_factory_(this) {
  DCHECK(message_center_);
  defer_timer_.reset(new base::OneShotTimer);
  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) {
  NotificationList::PopupNotifications notifications =
      message_center_->GetPopupNotifications();
  for (NotificationList::PopupNotifications::iterator iter =
           notifications.begin();
       iter != notifications.end(); ++iter) {
    Notification* notification = *iter;
    DCHECK(notification);

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

    // Don't remove the notification only when it's not pinned.
    if (!notification->pinned())
      message_center_->RemoveNotification(notification_id, by_user);
    else
      message_center_->MarkSinglePopupAsShown(notification_id, true /* read */);

    break;
  }
}

std::unique_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::ClickOnSettingsButton(
    const std::string& notification_id) {
  message_center_->ClickOnSettingsButton(notification_id);
}

void MessagePopupCollection::UpdateNotificationSize(
    const std::string& notification_id) {
  OnNotificationUpdated(notification_id);
}

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() {
  if (message_center_->IsMessageCenterVisible()) {
    DCHECK_EQ(0u, message_center_->GetPopupNotifications().size());
    return;
  }

  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;

    MessageView* view;
    // Create top-level notification.
#if defined(OS_CHROMEOS)
    if ((*iter)->pinned()) {
      Notification notification = *(*iter);
      // Override pinned status, since toasts should be closable even when it's
      // pinned.
      notification.set_pinned(false);
      view = MessageViewFactory::Create(NULL, notification, true);
    } else
#endif  // defined(OS_CHROMEOS)
    {
      view = MessageViewFactory::Create(NULL, *(*iter), true);
    }

    view->set_context_menu_controller(context_menu_controller_.get());
    int view_height = ToastContentsView::GetToastSizeForView(view).height();
    int height_available =
        top_down ? alignment_delegate_->GetWorkArea().bottom() - base
                 : base - alignment_delegate_->GetWorkArea().y();

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

    ToastContentsView* toast = new ToastContentsView(
        (*iter)->id(), alignment_delegate_, 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::GetInstance()) {
      views::ViewsDelegate::GetInstance()->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_->GetWorkArea().bottom() - bounds.bottom()
             : bounds.y() - alignment_delegate_->GetWorkArea().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 display::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
