// 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.

#import "ui/message_center/cocoa/popup_collection.h"

#import "ui/message_center/cocoa/notification_controller.h"
#import "ui/message_center/cocoa/popup_controller.h"
#include "ui/message_center/message_center.h"
#include "ui/message_center/message_center_observer.h"
#include "ui/message_center/message_center_style.h"

const float kAnimationDuration = 0.2;

@interface MCPopupCollection (Private)
// Returns the primary screen's visible frame rectangle.
- (NSRect)screenFrame;

// Shows a popup, if there is room on-screen, for the given notification.
// Returns YES if the notification was actually displayed.
- (BOOL)addNotification:(const message_center::Notification*)notification;

// Updates the contents of the notification with the given ID.
- (void)updateNotification:(const std::string&)notificationID;

// Removes a popup from the screen and lays out new notifications that can
// now potentially fit on the screen.
- (void)removeNotification:(const std::string&)notificationID;

// Closes all the popups.
- (void)removeAllNotifications;

// Returns the index of the popup showing the notification with the given ID.
- (NSUInteger)indexOfPopupWithNotificationID:(const std::string&)notificationID;

// Repositions all popup notifications if needed.
- (void)layoutNotifications;

// Fits as many new notifications as possible on screen.
- (void)layoutNewNotifications;

// Process notifications pending to remove when no animation is being played.
- (void)processPendingRemoveNotifications;

// Process notifications pending to update when no animation is being played.
- (void)processPendingUpdateNotifications;
@end

namespace {

class PopupCollectionObserver : public message_center::MessageCenterObserver {
 public:
  PopupCollectionObserver(message_center::MessageCenter* message_center,
                          MCPopupCollection* popup_collection)
      : message_center_(message_center),
        popup_collection_(popup_collection) {
    message_center_->AddObserver(this);
  }

  virtual ~PopupCollectionObserver() {
    message_center_->RemoveObserver(this);
  }

  virtual void OnNotificationAdded(
      const std::string& notification_id) OVERRIDE {
    [popup_collection_ layoutNewNotifications];
  }

  virtual void OnNotificationRemoved(const std::string& notification_id,
                                     bool user_id) OVERRIDE {
    [popup_collection_ removeNotification:notification_id];
  }

  virtual void OnNotificationUpdated(
      const std::string& notification_id) OVERRIDE {
    [popup_collection_ updateNotification:notification_id];
  }

 private:
  message_center::MessageCenter* message_center_;  // Weak, global.

  MCPopupCollection* popup_collection_;  // Weak, owns this.
};

}  // namespace

@implementation MCPopupCollection

- (id)initWithMessageCenter:(message_center::MessageCenter*)messageCenter {
  if ((self = [super init])) {
    messageCenter_ = messageCenter;
    observer_.reset(new PopupCollectionObserver(messageCenter_, self));
    popups_.reset([[NSMutableArray alloc] init]);
    popupsBeingRemoved_.reset([[NSMutableArray alloc] init]);
    popupAnimationDuration_ = kAnimationDuration;
  }
  return self;
}

- (void)dealloc {
  [popupsBeingRemoved_ makeObjectsPerformSelector:
      @selector(markPopupCollectionGone)];
  [self removeAllNotifications];
  [super dealloc];
}

- (BOOL)isAnimating {
  return !animatingNotificationIDs_.empty();
}

- (NSTimeInterval)popupAnimationDuration {
  return popupAnimationDuration_;
}

- (void)onPopupAnimationEnded:(const std::string&)notificationID {
  NSUInteger index = [popupsBeingRemoved_ indexOfObjectPassingTest:
      ^BOOL(id popup, NSUInteger index, BOOL* stop) {
          return [popup notificationID] == notificationID;
      }];
  if (index != NSNotFound)
    [popupsBeingRemoved_ removeObjectAtIndex:index];

  animatingNotificationIDs_.erase(notificationID);
  if (![self isAnimating])
    [self layoutNotifications];

  // Give the testing code a chance to do something, i.e. quitting the test
  // run loop.
  if (![self isAnimating] && testingAnimationEndedCallback_)
    testingAnimationEndedCallback_.get()();
}

// Testing API /////////////////////////////////////////////////////////////////

- (NSArray*)popups {
  return popups_.get();
}

- (void)setScreenFrame:(NSRect)frame {
  testingScreenFrame_ = frame;
}

- (void)setAnimationDuration:(NSTimeInterval)duration {
  popupAnimationDuration_ = duration;
}

- (void)setAnimationEndedCallback:
    (message_center::AnimationEndedCallback)callback {
  testingAnimationEndedCallback_.reset(Block_copy(callback));
}

// Private /////////////////////////////////////////////////////////////////////

- (NSRect)screenFrame {
  if (!NSIsEmptyRect(testingScreenFrame_))
    return testingScreenFrame_;
  return [[[NSScreen screens] objectAtIndex:0] visibleFrame];
}

- (BOOL)addNotification:(const message_center::Notification*)notification {
  // Wait till all existing animations end.
  if ([self isAnimating])
    return NO;

  // The popup is owned by itself. It will be released at close.
  MCPopupController* popup =
      [[MCPopupController alloc] initWithNotification:notification
                                        messageCenter:messageCenter_
                                      popupCollection:self];

  NSRect screenFrame = [self screenFrame];
  NSRect popupFrame = [popup bounds];

  CGFloat x = NSMaxX(screenFrame) - message_center::kMarginBetweenItems -
      NSWidth(popupFrame);
  CGFloat y = 0;

  MCPopupController* bottomPopup = [popups_ lastObject];
  if (!bottomPopup) {
    y = NSMaxY(screenFrame);
  } else {
    y = NSMinY([bottomPopup bounds]);
  }

  y -= message_center::kMarginBetweenItems + NSHeight(popupFrame);

  if (y > NSMinY(screenFrame)) {
    animatingNotificationIDs_.insert(notification->id());
    NSRect bounds = [popup bounds];
    bounds.origin.x = x;
    bounds.origin.y = y;
    [popup showWithAnimation:bounds];
    [popups_ addObject:popup];
    messageCenter_->DisplayedNotification(
        notification->id(), message_center::DISPLAY_SOURCE_POPUP);
    return YES;
  }

  // The popup cannot fit on screen, so it has to be released now.
  [popup release];
  return NO;
}

- (void)updateNotification:(const std::string&)notificationID {
  // The notification may not be on screen. Create it if needed.
  if ([self indexOfPopupWithNotificationID:notificationID] == NSNotFound) {
    [self layoutNewNotifications];
    return;
  }

  // Don't bother with the update if the notification is going to be removed.
  if (pendingRemoveNotificationIDs_.find(notificationID) !=
          pendingRemoveNotificationIDs_.end()) {
    return;
  }

  pendingUpdateNotificationIDs_.insert(notificationID);
  [self processPendingUpdateNotifications];
}

- (void)removeNotification:(const std::string&)notificationID {
  // The notification may not be on screen.
  if ([self indexOfPopupWithNotificationID:notificationID] == NSNotFound)
    return;

  // Don't bother with the update if the notification is going to be removed.
  pendingUpdateNotificationIDs_.erase(notificationID);

  pendingRemoveNotificationIDs_.insert(notificationID);
  [self processPendingRemoveNotifications];
}

- (void)removeAllNotifications {
  // In rare cases, the popup collection would be gone while an animation is
  // still playing. For exmaple, the test code could show a new notification
  // and dispose the collection immediately. Close the popup without animation
  // when this is the case.
  if ([self isAnimating])
    [popups_ makeObjectsPerformSelector:@selector(close)];
  else
    [popups_ makeObjectsPerformSelector:@selector(closeWithAnimation)];
  [popups_ makeObjectsPerformSelector:@selector(markPopupCollectionGone)];
  [popups_ removeAllObjects];
}

- (NSUInteger)indexOfPopupWithNotificationID:
    (const std::string&)notificationID {
  return [popups_ indexOfObjectPassingTest:
      ^BOOL(id popup, NSUInteger index, BOOL* stop) {
          return [popup notificationID] == notificationID;
      }];
}

- (void)layoutNotifications {
  // Wait till all existing animations end.
  if ([self isAnimating])
    return;

  NSRect screenFrame = [self screenFrame];

  // The popup starts at top-right corner.
  CGFloat maxY = NSMaxY(screenFrame);

  // Iterate all notifications and reposition each if needed. If one does not
  // fit on screen, close it and any other on-screen popups that come after it.
  NSUInteger removeAt = NSNotFound;
  for (NSUInteger i = 0; i < [popups_ count]; ++i) {
    MCPopupController* popup = [popups_ objectAtIndex:i];
    NSRect oldFrame = [popup bounds];
    NSRect frame = oldFrame;
    frame.origin.y = maxY - message_center::kMarginBetweenItems -
                     NSHeight(frame);

    // If this popup does not fit on screen, stop repositioning and close this
    // and subsequent popups.
    if (NSMinY(frame) < NSMinY(screenFrame)) {
      removeAt = i;
      break;
    }

    if (!NSEqualRects(frame, oldFrame)) {
      [popup setBounds:frame];
      animatingNotificationIDs_.insert([popup notificationID]);
    }

    // Set the new maximum Y to be the bottom of this notification.
    maxY = NSMinY(frame);
  }

  if (removeAt != NSNotFound) {
    // Remove any popups that are on screen but no longer fit.
    while ([popups_ count] >= removeAt && [popups_ count]) {
      [[popups_ lastObject] close];
      [popups_ removeLastObject];
    }
  } else {
    [self layoutNewNotifications];
  }

  [self processPendingRemoveNotifications];
  [self processPendingUpdateNotifications];
}

- (void)layoutNewNotifications {
  // Wait till all existing animations end.
  if ([self isAnimating])
    return;

  // Display any new popups that can now fit on screen, starting from the
  // oldest notification that has not been shown up.
  const auto& allPopups = messageCenter_->GetPopupNotifications();
  for (auto it = allPopups.rbegin(); it != allPopups.rend(); ++it) {
    if ([self indexOfPopupWithNotificationID:(*it)->id()] == NSNotFound) {
      // If there's no room left on screen to display notifications, stop
      // trying.
      if (![self addNotification:*it])
        break;
    }
  }
}

- (void)processPendingRemoveNotifications {
  // Wait till all existing animations end.
  if ([self isAnimating])
    return;

  for (const auto& notificationID : pendingRemoveNotificationIDs_) {
    NSUInteger index = [self indexOfPopupWithNotificationID:notificationID];
    if (index != NSNotFound) {
      [[popups_ objectAtIndex:index] closeWithAnimation];
      animatingNotificationIDs_.insert(notificationID);

      // Still need to track popup object and only remove it after the animation
      // ends. We need to notify these objects that the collection is gone
      // in the collection destructor.
      [popupsBeingRemoved_ addObject:[popups_ objectAtIndex:index]];
      [popups_ removeObjectAtIndex:index];
    }
  }
  pendingRemoveNotificationIDs_.clear();
}

- (void)processPendingUpdateNotifications {
  // Wait till all existing animations end.
  if ([self isAnimating])
    return;

  if (pendingUpdateNotificationIDs_.empty())
    return;

  // Go through all model objects in the message center. If there is a replaced
  // notification, the controller's current model object may be stale.
  const auto& modelPopups = messageCenter_->GetPopupNotifications();
  for (auto iter = modelPopups.begin(); iter != modelPopups.end(); ++iter) {
    const std::string& notificationID = (*iter)->id();

    // Does the notification need to be updated?
    std::set<std::string>::iterator pendingUpdateIter =
        pendingUpdateNotificationIDs_.find(notificationID);
    if (pendingUpdateIter == pendingUpdateNotificationIDs_.end())
      continue;
    pendingUpdateNotificationIDs_.erase(pendingUpdateIter);

    // Is the notification still on screen?
    NSUInteger index = [self indexOfPopupWithNotificationID:notificationID];
    if (index == NSNotFound)
      continue;

    MCPopupController* popup = [popups_ objectAtIndex:index];

    CGFloat oldHeight =
        NSHeight([[[popup notificationController] view] frame]);
    CGFloat newHeight = NSHeight(
        [[popup notificationController] updateNotification:*iter]);

    // The notification has changed height. This requires updating the popup
    // window.
    if (oldHeight != newHeight) {
      NSRect popupFrame = [popup bounds];
      popupFrame.origin.y -= newHeight - oldHeight;
      popupFrame.size.height += newHeight - oldHeight;
      [popup setBounds:popupFrame];
      animatingNotificationIDs_.insert([popup notificationID]);
    }
  }

  // Notification update could be received when a notification is excluded from
  // the popup notification list but still remains in the full notification
  // list, as in clicking the popup. In that case, the popup should be closed.
  for (auto iter = pendingUpdateNotificationIDs_.begin();
       iter != pendingUpdateNotificationIDs_.end(); ++iter) {
    pendingRemoveNotificationIDs_.insert(*iter);
  }

  pendingUpdateNotificationIDs_.clear();

  // Start re-layout of all notifications, so that it readjusts the Y origin of
  // all updated popups and any popups that come below them.
  [self layoutNotifications];
}

@end
