// Copyright 2014 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 "chrome/browser/ui/cocoa/profiles/profile_menu_controller.h"

#include <stddef.h>

#include "base/mac/scoped_nsobject.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/sys_string_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/avatar_menu.h"
#include "chrome/browser/profiles/avatar_menu_observer.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_avatar_icon_util.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/profiles/profile_metrics.h"
#include "chrome/browser/profiles/profile_window.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_list_observer.h"
#include "chrome/browser/ui/cocoa/last_active_browser_cocoa.h"
#include "chrome/grit/generated_resources.h"
#include "components/signin/core/browser/account_consistency_method.h"
#include "ui/base/l10n/l10n_util_mac.h"
#include "ui/gfx/image/image.h"

namespace {

// Used in UMA histogram macros, shouldn't be reordered or renumbered
enum ValidateMenuItemSelector {
  UNKNOWN_SELECTOR = 0,
  NEW_PROFILE,
  EDIT_PROFILE,
  SWITCH_PROFILE_MENU,
  SWITCH_PROFILE_DOCK,
  MAX_VALIDATE_MENU_SELECTOR,
};

}  // namespace

@interface ProfileMenuController (Private)
- (void)initializeMenu;
@end

namespace ProfileMenuControllerInternal {

class Observer : public BrowserListObserver, public AvatarMenuObserver {
 public:
  Observer(ProfileMenuController* controller) : controller_(controller) {
    BrowserList::AddObserver(this);
  }

  ~Observer() override { BrowserList::RemoveObserver(this); }

  // BrowserListObserver:
  void OnBrowserAdded(Browser* browser) override {}
  void OnBrowserRemoved(Browser* browser) override {
    [controller_ activeBrowserChangedTo:chrome::GetLastActiveBrowser()];
  }
  void OnBrowserSetLastActive(Browser* browser) override {
    [controller_ activeBrowserChangedTo:browser];
  }

  // AvatarMenuObserver:
  void OnAvatarMenuChanged(AvatarMenu* menu) override {
    [controller_ rebuildMenu];
  }

 private:
  ProfileMenuController* controller_;  // Weak; owns this.
};

}  // namespace ProfileMenuControllerInternal

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

@implementation ProfileMenuController

- (id)initWithMainMenuItem:(NSMenuItem*)item {
  if ((self = [super init])) {
    mainMenuItem_ = item;

    base::scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle:
        l10n_util::GetNSStringWithFixup(IDS_PROFILES_OPTIONS_GROUP_NAME)]);
    [mainMenuItem_ setSubmenu:menu];

    // This object will be constructed as part of nib loading, which happens
    // before the message loop starts and g_browser_process is available.
    // Schedule this on the loop to do work when the browser is ready.
    [self performSelector:@selector(initializeMenu)
               withObject:nil
               afterDelay:0];
  }
  return self;
}

- (IBAction)switchToProfileFromMenu:(id)sender {
  avatarMenu_->SwitchToProfile([sender tag], false,
                               ProfileMetrics::SWITCH_PROFILE_MENU);
}

- (IBAction)switchToProfileFromDock:(id)sender {
  // Explicitly bring to the foreground when taking action from the dock.
  [NSApp activateIgnoringOtherApps:YES];
  avatarMenu_->SwitchToProfile([sender tag], false,
                               ProfileMetrics::SWITCH_PROFILE_DOCK);
}

- (IBAction)editProfile:(id)sender {
  avatarMenu_->EditProfile(avatarMenu_->GetActiveProfileIndex());
}

- (IBAction)newProfile:(id)sender {
  profiles::CreateAndSwitchToNewProfile(ProfileManager::CreateCallback(),
                                        ProfileMetrics::ADD_NEW_USER_MENU);
}

- (BOOL)insertItemsIntoMenu:(NSMenu*)menu
                   atOffset:(NSInteger)offset
                   fromDock:(BOOL)dock {
  if (!avatarMenu_)
    return NO;

  // Don't show the list of profiles in the dock if only one profile exists.
  if (dock && avatarMenu_->GetNumberOfItems() <= 1)
    return NO;

  if (dock) {
    NSString* headerName =
        l10n_util::GetNSStringWithFixup(IDS_PROFILES_OPTIONS_GROUP_NAME);
    base::scoped_nsobject<NSMenuItem> header(
        [[NSMenuItem alloc] initWithTitle:headerName
                                   action:NULL
                            keyEquivalent:@""]);
    [header setEnabled:NO];
    [menu insertItem:header atIndex:offset++];
  }

  for (size_t i = 0; i < avatarMenu_->GetNumberOfItems(); ++i) {
    const AvatarMenu::Item& itemData = avatarMenu_->GetItemAt(i);
    NSString* name = base::SysUTF16ToNSString(itemData.name);
    SEL action = dock ? @selector(switchToProfileFromDock:)
                      : @selector(switchToProfileFromMenu:);
    NSMenuItem* item = [self createItemWithTitle:name
                                          action:action];
    [item setTag:itemData.menu_index];
    if (dock) {
      [item setIndentationLevel:1];
    } else {
      gfx::Image itemIcon;
      // Always use the low-res, small default avatars in the menu.
      AvatarMenu::GetImageForMenuButton(itemData.profile_path, &itemIcon);

      // The image might be too large and need to be resized (i.e. if this is
      // a signed-in user using the GAIA profile photo).
      if (itemIcon.Width() > profiles::kAvatarIconWidth ||
          itemIcon.Height() > profiles::kAvatarIconHeight) {
        itemIcon = profiles::GetAvatarIconForWebUI(itemIcon, true);
      }
      DCHECK(itemIcon.Width() <= profiles::kAvatarIconWidth);
      DCHECK(itemIcon.Height() <= profiles::kAvatarIconHeight);
      [item setImage:itemIcon.ToNSImage()];
      [item setState:itemData.active ? NSOnState : NSOffState];
    }
    [menu insertItem:item atIndex:i + offset];
  }

  return YES;
}

- (BOOL)validateMenuItem:(NSMenuItem*)menuItem {
  // In guest mode, chrome://settings isn't available, so disallow creating
  // or editing a profile.
  Profile* activeProfile = ProfileManager::GetLastUsedProfile();
  if (activeProfile->IsGuestSession()) {
    return [menuItem action] != @selector(newProfile:) &&
           [menuItem action] != @selector(editProfile:);
  }

  size_t index = avatarMenu_->GetActiveProfileIndex();
  if (avatarMenu_->GetNumberOfItems() <= index) {
    ValidateMenuItemSelector currentSelector = UNKNOWN_SELECTOR;
    if ([menuItem action] == @selector(newProfile:))
      currentSelector = NEW_PROFILE;
    else if ([menuItem action] == @selector(editProfile:))
      currentSelector = EDIT_PROFILE;
    else if ([menuItem action] == @selector(switchToProfileFromMenu:))
      currentSelector = SWITCH_PROFILE_MENU;
    else if ([menuItem action] == @selector(switchToProfileFromDock:))
      currentSelector = SWITCH_PROFILE_DOCK;
    UMA_HISTOGRAM_BOOLEAN("Profile.ValidateMenuItemInvalidIndex.IsGuest",
                          activeProfile->IsGuestSession());
    UMA_HISTOGRAM_CUSTOM_COUNTS(
        "Profile.ValidateMenuItemInvalidIndex.ProfileCount",
        avatarMenu_->GetNumberOfItems(),
        1, 20, 20);
    UMA_HISTOGRAM_ENUMERATION("Profile.ValidateMenuItemInvalidIndex.Selector",
                              currentSelector,
                              MAX_VALIDATE_MENU_SELECTOR);

    return NO;
  }

  const AvatarMenu::Item& itemData = avatarMenu_->GetItemAt(index);
  if ([menuItem action] == @selector(switchToProfileFromDock:) ||
      [menuItem action] == @selector(switchToProfileFromMenu:)) {
    if (!itemData.legacy_supervised)
      return YES;

    return [menuItem tag] == static_cast<NSInteger>(itemData.menu_index);
  }

  if ([menuItem action] == @selector(newProfile:))
    return !itemData.legacy_supervised;

  return YES;
}

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

- (NSMenu*)menu {
  return [mainMenuItem_ submenu];
}

- (void)initializeMenu {
  observer_.reset(new ProfileMenuControllerInternal::Observer(self));
  avatarMenu_.reset(new AvatarMenu(
      &g_browser_process->profile_manager()->GetProfileAttributesStorage(),
      observer_.get(),
      NULL));
  avatarMenu_->RebuildMenu();

  [[self menu] addItem:[NSMenuItem separatorItem]];

  NSMenuItem* item = [self createItemWithTitle:
      l10n_util::GetNSStringWithFixup(IDS_PROFILES_MANAGE_BUTTON_LABEL)
                                        action:@selector(editProfile:)];
  [[self menu] addItem:item];

  [[self menu] addItem:[NSMenuItem separatorItem]];
  item = [self createItemWithTitle:l10n_util::GetNSStringWithFixup(
      IDS_PROFILES_CREATE_NEW_PROFILE_OPTION)
                            action:@selector(newProfile:)];
  [[self menu] addItem:item];

  [self rebuildMenu];
}

// Notifies the controller that the active browser has changed and that the
// menu item and menu need to be updated to reflect that.
- (void)activeBrowserChangedTo:(Browser*)browser {
  // Tell the menu that the browser has changed.
  avatarMenu_->ActiveBrowserChanged(browser);

  // If |browser| is NULL, it may be because the current profile was deleted
  // and there are no other loaded profiles. In this case, calling
  // |avatarMenu_->GetActiveProfileIndex()| may result in a profile being
  // loaded, which is inappropriate to do on the UI thread.
  //
  // An early return provides the desired behavior:
  //   a) If the profile was deleted, the menu would have been rebuilt and no
  //      profile will have a check mark.
  //   b) If the profile was not deleted, but there is no active browser, then
  //      the previous profile will remain checked.
  if (!browser)
    return;

  // Update the avatar menu to get the active item states. Don't call
  // avatarMenu_->GetActiveProfileIndex() as the index might be
  // incorrect if -activeBrowserChangedTo: is called while we deleting the
  // active profile and closing all its browser windows.
  avatarMenu_->RebuildMenu();

  // Update the state for the menu items.
  for (size_t i = 0; i < avatarMenu_->GetNumberOfItems(); ++i) {
    const AvatarMenu::Item& itemData = avatarMenu_->GetItemAt(i);
    [[[self menu] itemWithTag:itemData.menu_index]
        setState:itemData.active ? NSOnState : NSOffState];
  }
}

- (void)rebuildMenu {
  NSMenu* menu = [self menu];

  for (NSMenuItem* item = [menu itemAtIndex:0];
       ![item isSeparatorItem];
       item = [menu itemAtIndex:0]) {
    [menu removeItemAtIndex:0];
  }

  BOOL hasContent = [self insertItemsIntoMenu:menu atOffset:0 fromDock:NO];

  [mainMenuItem_ setHidden:!hasContent];
}

- (NSMenuItem*)createItemWithTitle:(NSString*)title action:(SEL)sel {
  base::scoped_nsobject<NSMenuItem> item(
      [[NSMenuItem alloc] initWithTitle:title action:sel keyEquivalent:@""]);
  [item setTarget:self];
  return [item.release() autorelease];
}

@end
