// 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 "chrome/browser/notifications/notification_ui_manager_mac.h"

#include "base/mac/cocoa_protocols.h"
#include "base/mac/mac_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/sys_string_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/notifications/notification.h"
#include "chrome/browser/notifications/balloon_notification_ui_manager.h"
#include "chrome/browser/notifications/message_center_notification_manager.h"
#include "chrome/browser/notifications/message_center_settings_controller.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_info_cache.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "ui/message_center/message_center_util.h"

@class NSUserNotificationCenter;

// Since NSUserNotification and NSUserNotificationCenter are new classes in
// 10.8, they cannot simply be declared with an @interface. An @implementation
// is needed to link, but providing one would cause a runtime conflict when
// running on 10.8. Instead, provide the interface defined as a protocol and
// use that instead, because sizeof(id<Protocol>) == sizeof(Class*). In order to
// instantiate, use NSClassFromString and simply assign the alloc/init'd result
// to an instance of the proper protocol. This way the compiler, linker, and
// loader are all happy. And the code isn't full of objc_msgSend.
@protocol CrUserNotification <NSObject>
@property(copy) NSString* title;
@property(copy) NSString* subtitle;
@property(copy) NSString* informativeText;
@property(copy) NSString* actionButtonTitle;
@property(copy) NSDictionary* userInfo;
@property(copy) NSDate* deliveryDate;
@property(copy) NSTimeZone* deliveryTimeZone;
@property(copy) NSDateComponents* deliveryRepeatInterval;
@property(readonly) NSDate* actualDeliveryDate;
@property(readonly, getter=isPresented) BOOL presented;
@property(readonly, getter=isRemote) BOOL remote;
@property(copy) NSString* soundName;
@property BOOL hasActionButton;
@end

@protocol CrUserNotificationCenter
+ (NSUserNotificationCenter*)defaultUserNotificationCenter;
@property(assign) id<NSUserNotificationCenterDelegate> delegate;
@property(copy) NSArray* scheduledNotifications;
- (void)scheduleNotification:(id<CrUserNotification>)notification;
- (void)removeScheduledNotification:(id<CrUserNotification>)notification;
@property(readonly) NSArray* deliveredNotifications;
- (void)deliverNotification:(id<CrUserNotification>)notification;
- (void)removeDeliveredNotification:(id<CrUserNotification>)notification;
- (void)removeAllDeliveredNotifications;
@end

////////////////////////////////////////////////////////////////////////////////

namespace {

// A "fun" way of saying:
//   +[NSUserNotificationCenter defaultUserNotificationCenter].
id<CrUserNotificationCenter> GetNotificationCenter() {
  return [NSClassFromString(@"NSUserNotificationCenter")
      performSelector:@selector(defaultUserNotificationCenter)];
}

// The key in NSUserNotification.userInfo that stores the C++ notification_id.
NSString* const kNotificationIDKey = @"notification_id";

}  // namespace

// A Cocoa class that can be the delegate of NSUserNotificationCenter that
// forwards commands to C++.
@interface NotificationCenterDelegate : NSObject
    <NSUserNotificationCenterDelegate> {
 @private
  NotificationUIManagerMac* manager_;  // Weak, owns self.
}
- (id)initWithManager:(NotificationUIManagerMac*)manager;
@end

////////////////////////////////////////////////////////////////////////////////

NotificationUIManagerMac::ControllerNotification::ControllerNotification(
    Profile* a_profile,
    id<CrUserNotification> a_view,
    Notification* a_model)
    : profile(a_profile),
      view(a_view),
      model(a_model) {
}

NotificationUIManagerMac::ControllerNotification::~ControllerNotification() {
  [view release];
  delete model;
}

////////////////////////////////////////////////////////////////////////////////

// static
NotificationUIManager* NotificationUIManager::Create(PrefService* local_state) {
  // TODO(rsesek): Remove this function and merge it with the one in
  // notification_ui_manager.cc.
  if (DelegatesToMessageCenter()) {
    ProfileInfoCache* profile_info_cache =
        &g_browser_process->profile_manager()->GetProfileInfoCache();
    scoped_ptr<message_center::NotifierSettingsProvider> settings_provider(
        new MessageCenterSettingsController(profile_info_cache));
    return new MessageCenterNotificationManager(
        g_browser_process->message_center(),
        local_state,
        settings_provider.Pass());
  }

  BalloonNotificationUIManager* balloon_manager = NULL;
  if (base::mac::IsOSMountainLionOrLater())
    balloon_manager = new NotificationUIManagerMac(local_state);
  else
    balloon_manager = new BalloonNotificationUIManager(local_state);
  balloon_manager->SetBalloonCollection(BalloonCollection::Create());
  return balloon_manager;
}

NotificationUIManagerMac::NotificationUIManagerMac(PrefService* local_state)
    : BalloonNotificationUIManager(local_state),
      delegate_([[NotificationCenterDelegate alloc] initWithManager:this]) {
  DCHECK(!GetNotificationCenter().delegate);
  GetNotificationCenter().delegate = delegate_.get();
}

NotificationUIManagerMac::~NotificationUIManagerMac() {
  CancelAll();
}

void NotificationUIManagerMac::Add(const Notification& notification,
                                   Profile* profile) {
  if (notification.is_html()) {
    BalloonNotificationUIManager::Add(notification, profile);
  } else {
    if (!notification.replace_id().empty()) {
      id<CrUserNotification> replacee = FindNotificationWithReplacementId(
          notification.replace_id());
      if (replacee)
        RemoveNotification(replacee);
    }

    // Owned by ControllerNotification.
    id<CrUserNotification> ns_notification =
        [[NSClassFromString(@"NSUserNotification") alloc] init];

    ns_notification.title = base::SysUTF16ToNSString(notification.title());
    ns_notification.subtitle =
        base::SysUTF16ToNSString(notification.display_source());
    ns_notification.informativeText =
        base::SysUTF16ToNSString(notification.message());
    ns_notification.userInfo =
        [NSDictionary dictionaryWithObject:base::SysUTF8ToNSString(
            notification.notification_id())
                                    forKey:kNotificationIDKey];
    ns_notification.hasActionButton = NO;

    notification_map_.insert(std::make_pair(
        notification.notification_id(),
        new ControllerNotification(profile,
                                   ns_notification,
                                   new Notification(notification))));

    [GetNotificationCenter() deliverNotification:ns_notification];
  }
}

std::set<std::string>
NotificationUIManagerMac::GetAllIdsByProfileAndSourceOrigin(
    Profile* profile, const GURL& source_origin) {
  std::set<std::string> notification_ids =
      BalloonNotificationUIManager::GetAllIdsByProfileAndSourceOrigin(
          profile, source_origin);

  for (NotificationMap::iterator it = notification_map_.begin();
       it != notification_map_.end(); ++it) {
    ControllerNotification* controller_notification = it->second;
    Notification* model = controller_notification->model;
    if (model->origin_url() == source_origin &&
        profile->IsSameProfile(controller_notification->profile)) {
      notification_ids.insert(model->notification_id());
    }
  }
  return notification_ids;
}

bool NotificationUIManagerMac::CancelById(const std::string& notification_id) {
  NotificationMap::iterator it = notification_map_.find(notification_id);
  if (it == notification_map_.end())
    return BalloonNotificationUIManager::CancelById(notification_id);

  return RemoveNotification(it->second->view);
}

bool NotificationUIManagerMac::CancelAllBySourceOrigin(
    const GURL& source_origin) {
  bool success =
      BalloonNotificationUIManager::CancelAllBySourceOrigin(source_origin);

  for (NotificationMap::iterator it = notification_map_.begin();
       it != notification_map_.end();) {
    if (it->second->model->origin_url() == source_origin) {
      // RemoveNotification will erase from the map, invalidating iterator
      // references to the removed element.
      success |= RemoveNotification((it++)->second->view);
    } else {
      ++it;
    }
  }

  return success;
}

bool NotificationUIManagerMac::CancelAllByProfile(Profile* profile) {
  bool success = BalloonNotificationUIManager::CancelAllByProfile(profile);

  for (NotificationMap::iterator it = notification_map_.begin();
       it != notification_map_.end();) {
    if (it->second->profile == profile) {
      // RemoveNotification will erase from the map, invalidating iterator
      // references to the removed element.
      success |= RemoveNotification((it++)->second->view);
    } else {
      ++it;
    }
  }

  return success;
}

void NotificationUIManagerMac::CancelAll() {
  id<CrUserNotificationCenter> center = GetNotificationCenter();

  // Calling RemoveNotification would loop many times over, so just replicate
  // a small bit of its logic here.
  for (NotificationMap::iterator it = notification_map_.begin();
       it != notification_map_.end();
       ++it) {
    it->second->model->Close(false);
    delete it->second;
  }
  notification_map_.clear();

  // Clean up any lingering ones in the system tray.
  [center removeAllDeliveredNotifications];

  BalloonNotificationUIManager::CancelAll();
}

const Notification*
NotificationUIManagerMac::FindNotificationWithCocoaNotification(
    id<CrUserNotification> notification) const {
  std::string notification_id = base::SysNSStringToUTF8(
      [notification.userInfo objectForKey:kNotificationIDKey]);

  NotificationMap::const_iterator it = notification_map_.find(notification_id);
  if (it == notification_map_.end())
    return NULL;

  return it->second->model;
}

bool NotificationUIManagerMac::RemoveNotification(
    id<CrUserNotification> notification) {
  std::string notification_id = base::SysNSStringToUTF8(
      [notification.userInfo objectForKey:kNotificationIDKey]);
  id<CrUserNotificationCenter> center = GetNotificationCenter();

  // First remove all Cocoa notifications from the center that match the
  // notification. Notifications in the system tray do not share pointer
  // equality with the balloons or any other message delievered to the
  // delegate, so this loop must be run through every time to clean up stale
  // notifications.
  NSArray* delivered_notifications = center.deliveredNotifications;
  for (id<CrUserNotification> delivered in delivered_notifications) {
    if ([delivered isEqual:notification]) {
      [center removeDeliveredNotification:delivered];
    }
  }

  // Then clean up the C++ model side.
  NotificationMap::iterator it = notification_map_.find(notification_id);
  if (it == notification_map_.end())
    return false;

  it->second->model->Close(false);
  delete it->second;
  notification_map_.erase(it);

  return true;
}

id<CrUserNotification>
NotificationUIManagerMac::FindNotificationWithReplacementId(
    const string16& replacement_id) const {
  for (NotificationMap::const_iterator it = notification_map_.begin();
       it != notification_map_.end();
       ++it) {
    if (it->second->model->replace_id() == replacement_id)
      return it->second->view;
  }
  return nil;
}

////////////////////////////////////////////////////////////////////////////////

@implementation NotificationCenterDelegate

- (id)initWithManager:(NotificationUIManagerMac*)manager {
  if ((self = [super init])) {
    CHECK(manager);
    manager_ = manager;
  }
  return self;
}

- (void)userNotificationCenter:(NSUserNotificationCenter*)center
        didDeliverNotification:(id<CrUserNotification>)nsNotification {
  const Notification* notification =
      manager_->FindNotificationWithCocoaNotification(nsNotification);
  if (notification)
    notification->Display();
}

- (void)userNotificationCenter:(NSUserNotificationCenter*)center
       didActivateNotification:(id<CrUserNotification>)nsNotification {
  const Notification* notification =
      manager_->FindNotificationWithCocoaNotification(nsNotification);
  if (notification)
    notification->Click();
}

- (BOOL)userNotificationCenter:(NSUserNotificationCenter*)center
     shouldPresentNotification:(id<CrUserNotification>)nsNotification {
  // Always display notifications, regardless of whether the app is foreground.
  return YES;
}

@end
