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

#import "chrome/browser/ui/cocoa/presentation_mode_controller.h"

#include <algorithm>

#include "base/command_line.h"
#import "base/mac/mac_util.h"
#include "chrome/browser/fullscreen.h"
#import "chrome/browser/ui/cocoa/browser_window_controller.h"
#include "chrome/common/chrome_switches.h"
#import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h"

NSString* const kWillEnterFullscreenNotification =
    @"WillEnterFullscreenNotification";
NSString* const kWillLeaveFullscreenNotification =
    @"WillLeaveFullscreenNotification";

namespace {
// The activation zone for the main menu is 4 pixels high; if we make it any
// smaller, then the menu can be made to appear without the bar sliding down.
const CGFloat kDropdownActivationZoneHeight = 4;
const NSTimeInterval kDropdownAnimationDuration = 0.12;
const NSTimeInterval kMouseExitCheckDelay = 0.1;
// This show delay attempts to match the delay for the main menu.
const NSTimeInterval kDropdownShowDelay = 0.3;
const NSTimeInterval kDropdownHideDelay = 0.2;

// The amount by which the floating bar is offset downwards (to avoid the menu)
// in presentation mode. (We can't use |-[NSMenu menuBarHeight]| since it
// returns 0 when the menu bar is hidden.)
const CGFloat kFloatingBarVerticalOffset = 22;

}  // end namespace


// Helper class to manage animations for the dropdown bar.  Calls
// [PresentationModeController changeFloatingBarShownFraction] once per
// animation step.
@interface DropdownAnimation : NSAnimation {
 @private
  PresentationModeController* controller_;
  CGFloat startFraction_;
  CGFloat endFraction_;
}

@property(readonly, nonatomic) CGFloat startFraction;
@property(readonly, nonatomic) CGFloat endFraction;

// Designated initializer.  Asks |controller| for the current shown fraction, so
// if the bar is already partially shown or partially hidden, the animation
// duration may be less than |fullDuration|.
- (id)initWithFraction:(CGFloat)fromFraction
          fullDuration:(CGFloat)fullDuration
        animationCurve:(NSAnimationCurve)animationCurve
            controller:(PresentationModeController*)controller;

@end

@implementation DropdownAnimation

@synthesize startFraction = startFraction_;
@synthesize endFraction = endFraction_;

- (id)initWithFraction:(CGFloat)toFraction
          fullDuration:(CGFloat)fullDuration
        animationCurve:(NSAnimationCurve)animationCurve
            controller:(PresentationModeController*)controller {
  // Calculate the effective duration, based on the current shown fraction.
  DCHECK(controller);
  CGFloat fromFraction = [controller floatingBarShownFraction];
  CGFloat effectiveDuration = fabs(fullDuration * (fromFraction - toFraction));

  if ((self = [super gtm_initWithDuration:effectiveDuration
                                eventMask:NSLeftMouseDownMask
                           animationCurve:animationCurve])) {
    startFraction_ = fromFraction;
    endFraction_ = toFraction;
    controller_ = controller;
  }
  return self;
}

// Called once per animation step.  Overridden to change the floating bar's
// position based on the animation's progress.
- (void)setCurrentProgress:(NSAnimationProgress)progress {
  CGFloat fraction =
      startFraction_ + (progress * (endFraction_ - startFraction_));
  [controller_ changeFloatingBarShownFraction:fraction];
}

@end


@interface PresentationModeController (PrivateMethods)

// Returns YES if the window is on the primary screen.
- (BOOL)isWindowOnPrimaryScreen;

// Returns YES if it is ok to show and hide the menu bar in response to the
// overlay opening and closing.  Will return NO if the window is not main or not
// on the primary monitor.
- (BOOL)shouldToggleMenuBar;

// Returns |kFullScreenModeHideAll| when the overlay is hidden and
// |kFullScreenModeHideDock| when the overlay is shown.
- (base::mac::FullScreenMode)desiredSystemFullscreenMode;

// Change the overlay to the given fraction, with or without animation. Only
// guaranteed to work properly with |fraction == 0| or |fraction == 1|. This
// performs the show/hide (animation) immediately. It does not touch the timers.
- (void)changeOverlayToFraction:(CGFloat)fraction
                  withAnimation:(BOOL)animate;

// Schedule the floating bar to be shown/hidden because of mouse position.
- (void)scheduleShowForMouse;
- (void)scheduleHideForMouse;

// Set up the tracking area used to activate the sliding bar or keep it active
// using with the rectangle in |trackingAreaBounds_|, or remove the tracking
// area if one was previously set up.
- (void)setupTrackingArea;
- (void)removeTrackingAreaIfNecessary;

// Returns YES if the mouse is currently in any current tracking rectangle, NO
// otherwise.
- (BOOL)mouseInsideTrackingRect;

// The tracking area can "falsely" report exits when the menu slides down over
// it. In that case, we have to monitor for a "real" mouse exit on a timer.
// |-setupMouseExitCheck| schedules a check; |-cancelMouseExitCheck| cancels any
// scheduled check.
- (void)setupMouseExitCheck;
- (void)cancelMouseExitCheck;

// Called (after a delay) by |-setupMouseExitCheck|, to check whether the mouse
// has exited or not; if it hasn't, it will schedule another check.
- (void)checkForMouseExit;

// Start timers for showing/hiding the floating bar.
- (void)startShowTimer;
- (void)startHideTimer;
- (void)cancelShowTimer;
- (void)cancelHideTimer;
- (void)cancelAllTimers;

// Methods called when the show/hide timers fire. Do not call directly.
- (void)showTimerFire:(NSTimer*)timer;
- (void)hideTimerFire:(NSTimer*)timer;

// Stops any running animations, removes tracking areas, etc.
- (void)cleanup;

// Shows and hides the UI associated with this window being active (having main
// status).  This includes hiding the menu bar.  These functions are called when
// the window gains or loses main status as well as in |-cleanup|.
- (void)showActiveWindowUI;
- (void)hideActiveWindowUI;

@end


@implementation PresentationModeController

@synthesize inPresentationMode = inPresentationMode_;

- (id)initWithBrowserController:(BrowserWindowController*)controller {
  if ((self = [super init])) {
    browserController_ = controller;
    systemFullscreenMode_ = base::mac::kFullScreenModeNormal;
  }

  // Let the world know what we're up to.
  [[NSNotificationCenter defaultCenter]
    postNotificationName:kWillEnterFullscreenNotification
                  object:nil];

  return self;
}

- (void)dealloc {
  DCHECK(!inPresentationMode_);
  DCHECK(!trackingArea_);
  [super dealloc];
}

- (void)enterPresentationModeForContentView:(NSView*)contentView
                               showDropdown:(BOOL)showDropdown {
  DCHECK(!inPresentationMode_);
  enteringPresentationMode_ = YES;
  inPresentationMode_ = YES;
  contentView_ = contentView;
  [self changeFloatingBarShownFraction:(showDropdown ? 1 : 0)];

  // Register for notifications.  Self is removed as an observer in |-cleanup|.
  NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
  NSWindow* window = [browserController_ window];

  // Disable these notifications on Lion as they cause crashes.
  // TODO(rohitrao): Figure out what happens if a fullscreen window changes
  // monitors on Lion.
  if (base::mac::IsOSSnowLeopard()) {
    [nc addObserver:self
           selector:@selector(windowDidChangeScreen:)
               name:NSWindowDidChangeScreenNotification
             object:window];

    [nc addObserver:self
           selector:@selector(windowDidMove:)
               name:NSWindowDidMoveNotification
             object:window];
  }

  [nc addObserver:self
         selector:@selector(windowDidBecomeMain:)
             name:NSWindowDidBecomeMainNotification
           object:window];

  [nc addObserver:self
         selector:@selector(windowDidResignMain:)
             name:NSWindowDidResignMainNotification
           object:window];

  enteringPresentationMode_ = NO;
}

- (void)exitPresentationMode {
  [[NSNotificationCenter defaultCenter]
    postNotificationName:kWillLeaveFullscreenNotification
                  object:nil];
  DCHECK(inPresentationMode_);
  inPresentationMode_ = NO;
  [self cleanup];
}

- (void)windowDidChangeScreen:(NSNotification*)notification {
  [browserController_ resizeFullscreenWindow];
}

- (void)windowDidMove:(NSNotification*)notification {
  [browserController_ resizeFullscreenWindow];
}

- (void)windowDidBecomeMain:(NSNotification*)notification {
  [self showActiveWindowUI];
}

- (void)windowDidResignMain:(NSNotification*)notification {
  [self hideActiveWindowUI];
}

- (CGFloat)floatingBarVerticalOffset {
  return [self isWindowOnPrimaryScreen] ? kFloatingBarVerticalOffset : 0;
}

- (void)overlayFrameChanged:(NSRect)frame {
  if (!inPresentationMode_)
    return;

  // Make sure |trackingAreaBounds_| always reflects either the tracking area or
  // the desired tracking area.
  trackingAreaBounds_ = frame;
  // The tracking area should always be at least the height of activation zone.
  NSRect contentBounds = [contentView_ bounds];
  trackingAreaBounds_.origin.y =
      std::min(trackingAreaBounds_.origin.y,
               NSMaxY(contentBounds) - kDropdownActivationZoneHeight);
  trackingAreaBounds_.size.height =
      NSMaxY(contentBounds) - trackingAreaBounds_.origin.y + 1;

  // If an animation is currently running, do not set up a tracking area now.
  // Instead, leave it to be created it in |-animationDidEnd:|.
  if (currentAnimation_)
    return;

  // If this is part of the initial setup, lock bar visibility if the mouse is
  // within the tracking area bounds.
  if (enteringPresentationMode_ && [self mouseInsideTrackingRect])
    [browserController_ lockBarVisibilityForOwner:self
                                    withAnimation:NO
                                            delay:NO];
  [self setupTrackingArea];
}

- (void)ensureOverlayShownWithAnimation:(BOOL)animate delay:(BOOL)delay {
  if (!inPresentationMode_)
    return;

  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode))
    return;

  if (animate) {
    if (delay) {
      [self startShowTimer];
    } else {
      [self cancelAllTimers];
      [self changeOverlayToFraction:1 withAnimation:YES];
    }
  } else {
    DCHECK(!delay);
    [self cancelAllTimers];
    [self changeOverlayToFraction:1 withAnimation:NO];
  }
}

- (void)ensureOverlayHiddenWithAnimation:(BOOL)animate delay:(BOOL)delay {
  if (!inPresentationMode_)
    return;

  if (animate) {
    if (delay) {
      [self startHideTimer];
    } else {
      [self cancelAllTimers];
      [self changeOverlayToFraction:0 withAnimation:YES];
    }
  } else {
    DCHECK(!delay);
    [self cancelAllTimers];
    [self changeOverlayToFraction:0 withAnimation:NO];
  }
}

- (void)cancelAnimationAndTimers {
  [self cancelAllTimers];
  [currentAnimation_ stopAnimation];
  currentAnimation_.reset();
}

- (CGFloat)floatingBarShownFraction {
  return [browserController_ floatingBarShownFraction];
}

- (void)changeFloatingBarShownFraction:(CGFloat)fraction {
  [browserController_ setFloatingBarShownFraction:fraction];

  base::mac::FullScreenMode desiredMode = [self desiredSystemFullscreenMode];
  if (desiredMode != systemFullscreenMode_ && [self shouldToggleMenuBar]) {
    if (systemFullscreenMode_ == base::mac::kFullScreenModeNormal)
      base::mac::RequestFullScreen(desiredMode);
    else
      base::mac::SwitchFullScreenModes(systemFullscreenMode_, desiredMode);
    systemFullscreenMode_ = desiredMode;
  }
}

// Used to activate the floating bar in presentation mode.
- (void)mouseEntered:(NSEvent*)event {
  DCHECK(inPresentationMode_);

  // Having gotten a mouse entered, we no longer need to do exit checks.
  [self cancelMouseExitCheck];

  NSTrackingArea* trackingArea = [event trackingArea];
  if (trackingArea == trackingArea_) {
    // The tracking area shouldn't be active during animation.
    DCHECK(!currentAnimation_);
    [self scheduleShowForMouse];
  }
}

// Used to deactivate the floating bar in presentation mode.
- (void)mouseExited:(NSEvent*)event {
  DCHECK(inPresentationMode_);

  NSTrackingArea* trackingArea = [event trackingArea];
  if (trackingArea == trackingArea_) {
    // The tracking area shouldn't be active during animation.
    DCHECK(!currentAnimation_);

    // We can get a false mouse exit when the menu slides down, so if the mouse
    // is still actually over the tracking area, we ignore the mouse exit, but
    // we set up to check the mouse position again after a delay.
    if ([self mouseInsideTrackingRect]) {
      [self setupMouseExitCheck];
      return;
    }

    [self scheduleHideForMouse];
  }
}

- (void)animationDidStop:(NSAnimation*)animation {
  // Reset the |currentAnimation_| pointer now that the animation is over.
  currentAnimation_.reset();

  // Invariant says that the tracking area is not installed while animations are
  // in progress. Ensure this is true.
  DCHECK(!trackingArea_);
  [self removeTrackingAreaIfNecessary];  // For paranoia.

  // Don't automatically set up a new tracking area. When explicitly stopped,
  // either another animation is going to start immediately or the state will be
  // changed immediately.
}

- (void)animationDidEnd:(NSAnimation*)animation {
  [self animationDidStop:animation];

  // |trackingAreaBounds_| contains the correct tracking area bounds, including
  // |any updates that may have come while the animation was running. Install a
  // new tracking area with these bounds.
  [self setupTrackingArea];

  // TODO(viettrungluu): Better would be to check during the animation; doing it
  // here means that the timing is slightly off.
  if (![self mouseInsideTrackingRect])
    [self scheduleHideForMouse];
}

@end


@implementation PresentationModeController (PrivateMethods)

- (BOOL)isWindowOnPrimaryScreen {
  NSScreen* screen = [[browserController_ window] screen];
  NSScreen* primaryScreen = [[NSScreen screens] objectAtIndex:0];
  return (screen == primaryScreen);
}

- (BOOL)shouldToggleMenuBar {
  return !chrome::mac::SupportsSystemFullscreen() &&
         [self isWindowOnPrimaryScreen] &&
         [[browserController_ window] isMainWindow];
}

- (base::mac::FullScreenMode)desiredSystemFullscreenMode {
  if ([browserController_ floatingBarShownFraction] >= 1.0)
    return base::mac::kFullScreenModeHideDock;
  return base::mac::kFullScreenModeHideAll;
}

- (void)changeOverlayToFraction:(CGFloat)fraction
                  withAnimation:(BOOL)animate {
  // The non-animated case is really simple, so do it and return.
  if (!animate) {
    [currentAnimation_ stopAnimation];
    [self changeFloatingBarShownFraction:fraction];
    return;
  }

  // If we're already animating to the given fraction, then there's nothing more
  // to do.
  if (currentAnimation_ && [currentAnimation_ endFraction] == fraction)
    return;

  // In all other cases, we want to cancel any running animation (which may be
  // to show or to hide).
  [currentAnimation_ stopAnimation];

  // Now, if it happens to already be in the right state, there's nothing more
  // to do.
  if ([browserController_ floatingBarShownFraction] == fraction)
    return;

  // Create the animation and set it up.
  currentAnimation_.reset(
      [[DropdownAnimation alloc] initWithFraction:fraction
                                     fullDuration:kDropdownAnimationDuration
                                   animationCurve:NSAnimationEaseOut
                                       controller:self]);
  DCHECK(currentAnimation_);
  [currentAnimation_ setAnimationBlockingMode:NSAnimationNonblocking];
  [currentAnimation_ setDelegate:self];

  // If there is an existing tracking area, remove it. We do not track mouse
  // movements during animations (see class comment in the header file).
  [self removeTrackingAreaIfNecessary];

  [currentAnimation_ startAnimation];
}

- (void)scheduleShowForMouse {
  [browserController_ lockBarVisibilityForOwner:self
                                  withAnimation:YES
                                          delay:YES];
}

- (void)scheduleHideForMouse {
  [browserController_ releaseBarVisibilityForOwner:self
                                     withAnimation:YES
                                             delay:YES];
}

- (void)setupTrackingArea {
  if (trackingArea_) {
    // If the tracking rectangle is already |trackingAreaBounds_|, quit early.
    NSRect oldRect = [trackingArea_ rect];
    if (NSEqualRects(trackingAreaBounds_, oldRect))
      return;

    // Otherwise, remove it.
    [self removeTrackingAreaIfNecessary];
  }

  // Create and add a new tracking area for |frame|.
  trackingArea_.reset(
      [[NSTrackingArea alloc] initWithRect:trackingAreaBounds_
                                   options:NSTrackingMouseEnteredAndExited |
                                           NSTrackingActiveInKeyWindow
                                     owner:self
                                  userInfo:nil]);
  DCHECK(contentView_);
  [contentView_ addTrackingArea:trackingArea_];
}

- (void)removeTrackingAreaIfNecessary {
  if (trackingArea_) {
    DCHECK(contentView_);  // |contentView_| better be valid.
    [contentView_ removeTrackingArea:trackingArea_];
    trackingArea_.reset();
  }
}

- (BOOL)mouseInsideTrackingRect {
  NSWindow* window = [browserController_ window];
  NSPoint mouseLoc = [window mouseLocationOutsideOfEventStream];
  NSPoint mousePos = [contentView_ convertPoint:mouseLoc fromView:nil];
  return NSMouseInRect(mousePos, trackingAreaBounds_, [contentView_ isFlipped]);
}

- (void)setupMouseExitCheck {
  [self performSelector:@selector(checkForMouseExit)
             withObject:nil
             afterDelay:kMouseExitCheckDelay];
}

- (void)cancelMouseExitCheck {
  [NSObject cancelPreviousPerformRequestsWithTarget:self
      selector:@selector(checkForMouseExit) object:nil];
}

- (void)checkForMouseExit {
  if ([self mouseInsideTrackingRect])
    [self setupMouseExitCheck];
  else
    [self scheduleHideForMouse];
}

- (void)startShowTimer {
  // If there's already a show timer going, just keep it.
  if (showTimer_) {
    DCHECK([showTimer_ isValid]);
    DCHECK(!hideTimer_);
    return;
  }

  // Cancel the hide timer (if necessary) and set up the new show timer.
  [self cancelHideTimer];
  showTimer_.reset(
      [[NSTimer scheduledTimerWithTimeInterval:kDropdownShowDelay
                                        target:self
                                      selector:@selector(showTimerFire:)
                                      userInfo:nil
                                       repeats:NO] retain]);
  DCHECK([showTimer_ isValid]);  // This also checks that |showTimer_ != nil|.
}

- (void)startHideTimer {
  // If there's already a hide timer going, just keep it.
  if (hideTimer_) {
    DCHECK([hideTimer_ isValid]);
    DCHECK(!showTimer_);
    return;
  }

  // Cancel the show timer (if necessary) and set up the new hide timer.
  [self cancelShowTimer];
  hideTimer_.reset(
      [[NSTimer scheduledTimerWithTimeInterval:kDropdownHideDelay
                                        target:self
                                      selector:@selector(hideTimerFire:)
                                      userInfo:nil
                                       repeats:NO] retain]);
  DCHECK([hideTimer_ isValid]);  // This also checks that |hideTimer_ != nil|.
}

- (void)cancelShowTimer {
  [showTimer_ invalidate];
  showTimer_.reset();
}

- (void)cancelHideTimer {
  [hideTimer_ invalidate];
  hideTimer_.reset();
}

- (void)cancelAllTimers {
  [self cancelShowTimer];
  [self cancelHideTimer];
}

- (void)showTimerFire:(NSTimer*)timer {
  DCHECK_EQ(showTimer_, timer);  // This better be our show timer.
  [showTimer_ invalidate];       // Make sure it doesn't repeat.
  showTimer_.reset();            // And get rid of it.
  [self changeOverlayToFraction:1 withAnimation:YES];
}

- (void)hideTimerFire:(NSTimer*)timer {
  DCHECK_EQ(hideTimer_, timer);  // This better be our hide timer.
  [hideTimer_ invalidate];       // Make sure it doesn't repeat.
  hideTimer_.reset();            // And get rid of it.
  [self changeOverlayToFraction:0 withAnimation:YES];
}

- (void)cleanup {
  [self cancelMouseExitCheck];
  [self cancelAnimationAndTimers];
  [[NSNotificationCenter defaultCenter] removeObserver:self];

  [self removeTrackingAreaIfNecessary];
  contentView_ = nil;

  // This isn't tracked when not in presentation mode.
  [browserController_ releaseBarVisibilityForOwner:self
                                     withAnimation:NO
                                             delay:NO];

  // Call the main status resignation code to perform the associated cleanup,
  // since we will no longer be receiving actual status resignation
  // notifications.
  [self hideActiveWindowUI];

  // No more calls back up to the BWC.
  browserController_ = nil;
}

- (void)showActiveWindowUI {
  DCHECK_EQ(systemFullscreenMode_, base::mac::kFullScreenModeNormal);
  if (systemFullscreenMode_ != base::mac::kFullScreenModeNormal)
    return;

  if ([self shouldToggleMenuBar]) {
    base::mac::FullScreenMode desiredMode = [self desiredSystemFullscreenMode];
    base::mac::RequestFullScreen(desiredMode);
    systemFullscreenMode_ = desiredMode;
  }

  // TODO(rohitrao): Insert the Exit Fullscreen button.  http://crbug.com/35956
}

- (void)hideActiveWindowUI {
  if (systemFullscreenMode_ != base::mac::kFullScreenModeNormal) {
    base::mac::ReleaseFullScreen(systemFullscreenMode_);
    systemFullscreenMode_ = base::mac::kFullScreenModeNormal;
  }

  // TODO(rohitrao): Remove the Exit Fullscreen button.  http://crbug.com/35956
}

@end
