// Copyright 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 "chrome/browser/ui/app_list/app_list_service_mac.h"

#include <ApplicationServices/ApplicationServices.h>
#import <Cocoa/Cocoa.h>

#include "apps/app_shim/app_shim_mac.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/lazy_instance.h"
#include "base/memory/singleton.h"
#include "base/message_loop/message_loop.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
#include "chrome/browser/ui/app_list/app_list_controller_delegate_impl.h"
#include "chrome/browser/ui/app_list/app_list_service.h"
#include "chrome/browser/ui/app_list/app_list_service_impl.h"
#include "chrome/browser/ui/app_list/app_list_util.h"
#include "chrome/browser/ui/app_list/app_list_view_delegate.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/extensions/application_launch.h"
#include "chrome/browser/ui/web_applications/web_app_ui.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/browser/web_applications/web_app_mac.h"
#include "chrome/common/chrome_version_info.h"
#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
#include "chrome/common/mac/app_mode_common.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/browser_thread.h"
#include "grit/chrome_unscaled_resources.h"
#include "grit/google_chrome_strings.h"
#include "net/base/url_util.h"
#import "ui/app_list/cocoa/app_list_view_controller.h"
#import "ui/app_list/cocoa/app_list_window_controller.h"
#include "ui/app_list/search_box_model.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/display.h"
#include "ui/gfx/screen.h"

namespace gfx {
class ImageSkia;
}

// Controller for animations that show or hide the app list.
@interface AppListAnimationController : NSObject<NSAnimationDelegate> {
 @private
  // When closing, the window to close. Retained until the animation ends.
  base::scoped_nsobject<NSWindow> window_;
  // The animation started and owned by |self|. Reset when the animation ends.
  base::scoped_nsobject<NSViewAnimation> animation_;
}

// Returns whether |window_| is scheduled to be closed when the animation ends.
- (BOOL)isClosing;

// Animate |window| to show or close it, after cancelling any current animation.
// Translates from the current location to |targetOrigin| and fades in or out.
- (void)animateWindow:(NSWindow*)window
         targetOrigin:(NSPoint)targetOrigin
              closing:(BOOL)closing;

@end

namespace {

// Version of the app list shortcut version installed.
const int kShortcutVersion = 1;

// Duration of show and hide animations.
const NSTimeInterval kAnimationDuration = 0.2;

// Distance towards the screen edge that the app list moves from when showing.
const CGFloat kDistanceMovedOnShow = 20;

ShellIntegration::ShortcutInfo GetAppListShortcutInfo(
    const base::FilePath& profile_path) {
  ShellIntegration::ShortcutInfo shortcut_info;
  chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
  if (channel == chrome::VersionInfo::CHANNEL_CANARY) {
    shortcut_info.title =
        l10n_util::GetStringUTF16(IDS_APP_LIST_SHORTCUT_NAME_CANARY);
  } else {
    shortcut_info.title = l10n_util::GetStringUTF16(IDS_APP_LIST_SHORTCUT_NAME);
  }

  shortcut_info.extension_id = app_mode::kAppListModeId;
  shortcut_info.description = shortcut_info.title;
  shortcut_info.profile_path = profile_path;

  return shortcut_info;
}

void CreateAppListShim(const base::FilePath& profile_path) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  WebApplicationInfo web_app_info;
  ShellIntegration::ShortcutInfo shortcut_info =
      GetAppListShortcutInfo(profile_path);

  ResourceBundle& resource_bundle = ResourceBundle::GetSharedInstance();
  chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
  if (channel == chrome::VersionInfo::CHANNEL_CANARY) {
#if defined(GOOGLE_CHROME_BUILD)
    shortcut_info.favicon.Add(
        *resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_CANARY_16));
    shortcut_info.favicon.Add(
        *resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_CANARY_32));
    shortcut_info.favicon.Add(
        *resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_CANARY_128));
    shortcut_info.favicon.Add(
        *resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_CANARY_256));
#else
    NOTREACHED();
#endif
  } else {
    shortcut_info.favicon.Add(
        *resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_16));
    shortcut_info.favicon.Add(
        *resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_32));
    shortcut_info.favicon.Add(
        *resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_128));
    shortcut_info.favicon.Add(
        *resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_256));
  }

  ShellIntegration::ShortcutLocations shortcut_locations;
  PrefService* local_state = g_browser_process->local_state();
  int installed_version =
      local_state->GetInteger(prefs::kAppLauncherShortcutVersion);

  // If this is a first-time install, add a dock icon. Otherwise just update
  // the target, and wait for OSX to refresh its icon caches. This might not
  // occur until a reboot, but OSX does not offer a nicer way. Deleting cache
  // files on disk and killing processes can easily result in icon corruption.
  if (installed_version == 0)
    shortcut_locations.in_quick_launch_bar = true;

  web_app::CreateShortcuts(shortcut_info,
                           shortcut_locations,
                           web_app::SHORTCUT_CREATION_AUTOMATED);

  local_state->SetInteger(prefs::kAppLauncherShortcutVersion,
                          kShortcutVersion);
}

void CreateShortcutsInDefaultLocation(
    const ShellIntegration::ShortcutInfo& shortcut_info) {
  web_app::CreateShortcuts(shortcut_info,
                           ShellIntegration::ShortcutLocations(),
                           web_app::SHORTCUT_CREATION_BY_USER);
}

NSRunningApplication* ActiveApplicationNotChrome() {
  NSArray* applications = [[NSWorkspace sharedWorkspace] runningApplications];
  for (NSRunningApplication* application in applications) {
    if (![application isActive])
      continue;

    if ([application isEqual:[NSRunningApplication currentApplication]])
      return nil;  // Chrome is active.

    return application;
  }

  return nil;
}

enum DockLocation {
  DockLocationOtherDisplay,
  DockLocationBottom,
  DockLocationLeft,
  DockLocationRight,
};

DockLocation DockLocationInDisplay(const gfx::Display& display) {
  // Assume the dock occupies part of the work area either on the left, right or
  // bottom of the display. Note in the autohide case, it is always 4 pixels.
  const gfx::Rect work_area = display.work_area();
  const gfx::Rect display_bounds = display.bounds();
  if (work_area.bottom() != display_bounds.bottom())
    return DockLocationBottom;

  if (work_area.x() != display_bounds.x())
    return DockLocationLeft;

  if (work_area.right() != display_bounds.right())
    return DockLocationRight;

  return DockLocationOtherDisplay;
}

// If |work_area_edge| is too close to the |screen_edge| (e.g. autohide dock),
// adjust |anchor| away from the edge by a constant amount to reduce overlap and
// ensure the dock icon can still be clicked to dismiss the app list.
int AdjustPointForDynamicDock(int anchor, int screen_edge, int work_area_edge) {
  const int kAutohideDockThreshold = 10;
  const int kExtraDistance = 50;  // A dock with 40 items is about this size.
  if (abs(work_area_edge - screen_edge) > kAutohideDockThreshold)
    return anchor;

  return anchor +
      (screen_edge < work_area_edge ? kExtraDistance : -kExtraDistance);
}

void GetAppListWindowOrigins(
    NSWindow* window, NSPoint* target_origin, NSPoint* start_origin) {
  gfx::Screen* const screen = gfx::Screen::GetScreenFor([window contentView]);
  // Ensure y coordinates are flipped back into AppKit's coordinate system.
  const CGFloat max_y = NSMaxY([[[NSScreen screens] objectAtIndex:0] frame]);
  if (!CGCursorIsVisible()) {
    // If Chrome is the active application, display on the same display as
    // Chrome's keyWindow since this will catch activations triggered, e.g, via
    // WebStore install. If another application is active, OSX doesn't provide a
    // reliable way to get the display in use. Fall back to the primary display
    // since it has the menu bar and is likely to be correct, e.g., for
    // activations from Spotlight.
    const gfx::NativeView key_view = [[NSApp keyWindow] contentView];
    const gfx::Rect work_area = key_view && [NSApp isActive] ?
        screen->GetDisplayNearestWindow(key_view).work_area() :
        screen->GetPrimaryDisplay().work_area();
    *target_origin = NSMakePoint(work_area.x(), max_y - work_area.bottom());
    *start_origin = *target_origin;
    return;
  }

  gfx::Point anchor = screen->GetCursorScreenPoint();
  const gfx::Display display = screen->GetDisplayNearestPoint(anchor);
  const DockLocation dock_location = DockLocationInDisplay(display);
  const gfx::Rect display_bounds = display.bounds();

  if (dock_location == DockLocationOtherDisplay) {
    // Just display at the bottom-left of the display the cursor is on.
    *target_origin = NSMakePoint(display_bounds.x(),
                                 max_y - display_bounds.bottom());
    *start_origin = *target_origin;
    return;
  }

  // Anchor the center of the window in a region that prevents the window
  // showing outside of the work area.
  const NSSize window_size = [window frame].size;
  const gfx::Rect work_area = display.work_area();
  gfx::Rect anchor_area = work_area;
  anchor_area.Inset(window_size.width / 2, window_size.height / 2);
  anchor.SetToMax(anchor_area.origin());
  anchor.SetToMin(anchor_area.bottom_right());

  // Move anchor to the dock, keeping the other axis aligned with the cursor.
  switch (dock_location) {
    case DockLocationBottom:
      anchor.set_y(AdjustPointForDynamicDock(
          anchor_area.bottom(), display_bounds.bottom(), work_area.bottom()));
      break;
    case DockLocationLeft:
      anchor.set_x(AdjustPointForDynamicDock(
          anchor_area.x(), display_bounds.x(), work_area.x()));
      break;
    case DockLocationRight:
      anchor.set_x(AdjustPointForDynamicDock(
          anchor_area.right(), display_bounds.right(), work_area.right()));
      break;
    default:
      NOTREACHED();
  }

  *target_origin = NSMakePoint(anchor.x() - window_size.width / 2,
                               max_y - anchor.y() - window_size.height / 2);
  *start_origin = *target_origin;

  switch (dock_location) {
    case DockLocationBottom:
      start_origin->y -= kDistanceMovedOnShow;
      break;
    case DockLocationLeft:
      start_origin->x -= kDistanceMovedOnShow;
      break;
    case DockLocationRight:
      start_origin->x += kDistanceMovedOnShow;
      break;
    default:
      NOTREACHED();
  }
}

}  // namespace

AppListServiceMac::AppListServiceMac()
    : profile_(NULL) {
  animation_controller_.reset([[AppListAnimationController alloc] init]);
}

AppListServiceMac::~AppListServiceMac() {}

// static
AppListServiceMac* AppListServiceMac::GetInstance() {
  return Singleton<AppListServiceMac,
                   LeakySingletonTraits<AppListServiceMac> >::get();
}

void AppListServiceMac::Init(Profile* initial_profile) {
  // On Mac, Init() is called multiple times for a process: any time there is no
  // browser window open and a new window is opened, and during process startup
  // to handle the silent launch case (e.g. for app shims). In the startup case,
  // a profile has not yet been determined so |initial_profile| will be NULL.
  static bool init_called_with_profile = false;
  if (initial_profile && !init_called_with_profile) {
    init_called_with_profile = true;
    HandleCommandLineFlags(initial_profile);
    PrefService* local_state = g_browser_process->local_state();
    if (!IsAppLauncherEnabled()) {
      local_state->SetInteger(prefs::kAppLauncherShortcutVersion, 0);
    } else {
      int installed_shortcut_version =
          local_state->GetInteger(prefs::kAppLauncherShortcutVersion);

      if (kShortcutVersion > installed_shortcut_version)
        CreateShortcut();
    }
  }

  static bool init_called = false;
  if (init_called)
    return;

  init_called = true;
  apps::AppShimHandler::RegisterHandler(app_mode::kAppListModeId,
                                        AppListServiceMac::GetInstance());
}

Profile* AppListServiceMac::GetCurrentAppListProfile() {
  return profile_;
}

void AppListServiceMac::CreateForProfile(Profile* requested_profile) {
  if (profile_ == requested_profile)
    return;

  profile_ = requested_profile;

  if (window_controller_) {
    // Clear the search box.
    [[window_controller_ appListViewController] searchBoxModel]
        ->SetText(base::string16());
  } else {
    window_controller_.reset([[AppListWindowController alloc] init]);
  }

  scoped_ptr<app_list::AppListViewDelegate> delegate(
      new AppListViewDelegate(
          scoped_ptr<AppListControllerDelegate>(
              new AppListControllerDelegateImpl(this)), profile_));
  [[window_controller_ appListViewController] setDelegate:delegate.Pass()];
}

void AppListServiceMac::ShowForProfile(Profile* requested_profile) {
  if (requested_profile->IsManaged())
    return;

  InvalidatePendingProfileLoads();

  if (requested_profile == profile_) {
    ShowWindowNearDock();
    return;
  }

  SetProfilePath(requested_profile->GetPath());
  CreateForProfile(requested_profile);
  ShowWindowNearDock();
}

void AppListServiceMac::DismissAppList() {
  if (!IsAppListVisible())
    return;

  // If the app list is currently the main window, it will activate the next
  // Chrome window when dismissed. But if a different application was active
  // when the app list was shown, activate that instead.
  base::scoped_nsobject<NSRunningApplication> prior_app;
  if ([[window_controller_ window] isMainWindow])
    prior_app.swap(previously_active_application_);
  else
    previously_active_application_.reset();

  // If activation is successful, the app list will lose main status and try to
  // close itself again. It can't be closed in this runloop iteration without
  // OSX deciding to raise the next Chrome window, and _then_ activating the
  // application on top. This also occurs if no activation option is given.
  if ([prior_app activateWithOptions:NSApplicationActivateIgnoringOtherApps])
    return;

  [animation_controller_ animateWindow:[window_controller_ window]
                          targetOrigin:last_start_origin_
                               closing:YES];
}

bool AppListServiceMac::IsAppListVisible() const {
  return [[window_controller_ window] isVisible] &&
      ![animation_controller_ isClosing];
}

void AppListServiceMac::CreateShortcut() {
  CreateAppListShim(GetProfilePath(
      g_browser_process->profile_manager()->user_data_dir()));
}

NSWindow* AppListServiceMac::GetAppListWindow() {
  return [window_controller_ window];
}

AppListControllerDelegate* AppListServiceMac::CreateControllerDelegate() {
  return new AppListControllerDelegateImpl(this);
}

void AppListServiceMac::OnShimLaunch(apps::AppShimHandler::Host* host,
                                     apps::AppShimLaunchType launch_type,
                                     const std::vector<base::FilePath>& files) {
  if (IsAppListVisible())
    DismissAppList();
  else
    Show();

  // Always close the shim process immediately.
  host->OnAppLaunchComplete(apps::APP_SHIM_LAUNCH_DUPLICATE_HOST);
}

void AppListServiceMac::OnShimClose(apps::AppShimHandler::Host* host) {}

void AppListServiceMac::OnShimFocus(apps::AppShimHandler::Host* host,
                                    apps::AppShimFocusType focus_type,
                                    const std::vector<base::FilePath>& files) {}

void AppListServiceMac::OnShimSetHidden(apps::AppShimHandler::Host* host,
                                        bool hidden) {}

void AppListServiceMac::OnShimQuit(apps::AppShimHandler::Host* host) {}

void AppListServiceMac::ShowWindowNearDock() {
  if (IsAppListVisible())
    return;

  NSWindow* window = GetAppListWindow();
  DCHECK(window);
  NSPoint target_origin;
  GetAppListWindowOrigins(window, &target_origin, &last_start_origin_);
  [window setFrameOrigin:last_start_origin_];

  // Before activating, see if an application other than Chrome is currently the
  // active application, so that it can be reactivated when dismissing.
  previously_active_application_.reset([ActiveApplicationNotChrome() retain]);

  [animation_controller_ animateWindow:[window_controller_ window]
                          targetOrigin:target_origin
                               closing:NO];
  [window makeKeyAndOrderFront:nil];
  [NSApp activateIgnoringOtherApps:YES];
  RecordAppListLaunch();
}

// static
AppListService* AppListService::Get(chrome::HostDesktopType desktop_type) {
  return AppListServiceMac::GetInstance();
}

// static
void AppListService::InitAll(Profile* initial_profile) {
  AppListServiceMac::GetInstance()->Init(initial_profile);
}

@implementation AppListAnimationController

- (BOOL)isClosing {
  return !!window_;
}

- (void)animateWindow:(NSWindow*)window
         targetOrigin:(NSPoint)targetOrigin
              closing:(BOOL)closing {
  // First, stop the existing animation, if there is one.
  [animation_ stopAnimation];

  NSRect targetFrame = [window frame];
  targetFrame.origin = targetOrigin;

  // NSViewAnimation has a quirk when setting the curve to NSAnimationEaseOut
  // where it attempts to auto-reverse the animation. FadeOut becomes FadeIn
  // (good), but FrameKey is also switched (bad). So |targetFrame| needs to be
  // put on the StartFrameKey when using NSAnimationEaseOut for showing.
  NSArray* animationArray = @[
    @{
      NSViewAnimationTargetKey : window,
      NSViewAnimationEffectKey : NSViewAnimationFadeOutEffect,
      (closing ? NSViewAnimationEndFrameKey : NSViewAnimationStartFrameKey) :
          [NSValue valueWithRect:targetFrame]
    }
  ];
  animation_.reset(
      [[NSViewAnimation alloc] initWithViewAnimations:animationArray]);
  [animation_ setDuration:kAnimationDuration];
  [animation_ setDelegate:self];

  if (closing) {
    [animation_ setAnimationCurve:NSAnimationEaseIn];
    window_.reset([window retain]);
  } else {
    [window setAlphaValue:0.0f];
    [animation_ setAnimationCurve:NSAnimationEaseOut];
    window_.reset();
  }
  [animation_ startAnimation];
}

- (void)animationDidEnd:(NSAnimation*)animation {
  [window_ close];
  window_.reset();
  animation_.reset();

  apps::AppShimHandler::MaybeTerminate();
}

@end
