// 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 "ui/base/cocoa/constrained_window/constrained_window_animation.h"

#include <stdint.h>
#include <stdlib.h>

#include "base/files/file_path.h"
#include "base/location.h"
#import "base/mac/foundation_util.h"
#include "base/native_library.h"
#include "base/stl_util.h"
#include "ui/gfx/animation/tween.h"

// The window animations in this file use private APIs as described here:
// http://code.google.com/p/undocumented-goodness/source/browse/trunk/CoreGraphics/CGSPrivate.h
// There are two important things to keep in mind when modifying this file:
// - For most operations the origin of the coordinate system is top left.
// - Perspective and shear transformations get clipped if they are bigger
//   than the window size. This does not seem to apply to scale transformations.

// Length of the animation in seconds.
const NSTimeInterval kAnimationDuration = 0.18;

// The number of pixels above the final destination to animate from.
const CGFloat kShowHideVerticalOffset = 20;

// Scale the window by this factor when animating.
const CGFloat kShowHideScaleFactor = 0.99;

// Size of the perspective effect as a factor of the window width.
const CGFloat kShowHidePerspectiveFactor = 0.04;

// Forward declare private CoreGraphics APIs used to transform windows.
extern "C" {

typedef float float32;

typedef int32_t CGSWindow;
typedef int32_t CGSConnection;

typedef struct {
  float32 x;
  float32 y;
} MeshPoint;

typedef struct {
  MeshPoint local;
  MeshPoint global;
} CGPointWarp;

CGSConnection _CGSDefaultConnection();
CGError CGSSetWindowTransform(const CGSConnection cid,
                              const CGSWindow wid,
                              CGAffineTransform transform);
CGError CGSSetWindowWarp(const CGSConnection cid,
                         const CGSWindow wid,
                         int32_t w,
                         int32_t h,
                         CGPointWarp* mesh);
CGError CGSSetWindowAlpha(const CGSConnection cid,
                          const CGSWindow wid,
                          float32 alpha);

}  // extern "C"

namespace {

struct KeyFrame {
  float value;
  float scale;
};

// Get the window location relative to the top left of the main screen.
// Most Cocoa APIs use a coordinate system where the screen origin is the
// bottom left. The various CGSSetWindow* APIs use a coordinate system where
// the screen origin is the top left.
NSPoint GetCGSWindowScreenOrigin(NSWindow* window) {
  NSArray* screens = [NSScreen screens];
  if ([screens count] == 0)
    return NSZeroPoint;
  // Origin is relative to the screen with the menu bar (the screen at index 0).
  // Note, this is not the same as mainScreen which is the screen with the key
  // window.
  NSScreen* main_screen = screens[0];

  NSRect window_frame = [window frame];
  NSRect screen_frame = [main_screen frame];
  return NSMakePoint(NSMinX(window_frame),
                     NSHeight(screen_frame) - NSMaxY(window_frame));
}

// Set the transparency of the window.
void SetWindowAlpha(NSWindow* window, float alpha) {
  CGSConnection cid = _CGSDefaultConnection();
  CGSSetWindowAlpha(cid, [window windowNumber], alpha);
}

// Scales the window and translates it so that it stays centered relative
// to its original position.
void SetWindowScale(NSWindow* window, float scale) {
  CGFloat scale_delta = 1.0 - scale;
  CGFloat cur_scale = 1.0 + scale_delta;
  CGAffineTransform transform =
      CGAffineTransformMakeScale(cur_scale, cur_scale);

  // Translate the window to keep it centered at the original location.
  NSSize window_size = [window frame].size;
  CGFloat scale_offset_x = window_size.width * (1 - cur_scale) / 2.0;
  CGFloat scale_offset_y = window_size.height * (1 - cur_scale) / 2.0;

  NSPoint origin = GetCGSWindowScreenOrigin(window);
  CGFloat new_x = -origin.x + scale_offset_x;
  CGFloat new_y = -origin.y + scale_offset_y;
  transform = CGAffineTransformTranslate(transform, new_x, new_y);

  CGSConnection cid = _CGSDefaultConnection();
  CGSSetWindowTransform(cid, [window windowNumber], transform);
}

// Unsets any window warp that may have been previously applied.
// Window warp prevents other effects such as CGSSetWindowTransform from
// being applied.
void ClearWindowWarp(NSWindow* window) {
  CGSConnection cid = _CGSDefaultConnection();
  CGSSetWindowWarp(cid, [window windowNumber], 0, 0, NULL);
}

// Applies various transformations using a warp effect. The window is
// translated vertically by |y_offset|. The window is scaled by |scale| and
// translated so that the it remains centered relative to its original position.
// Finally, perspective is effect is applied by shrinking the top of the window.
void SetWindowWarp(NSWindow* window,
                   float y_offset,
                   float scale,
                   float perspective_offset) {
  NSRect win_rect = [window frame];
  win_rect.origin = NSZeroPoint;
  NSRect screen_rect = win_rect;
  screen_rect.origin = GetCGSWindowScreenOrigin(window);

  // Apply a vertical translate.
  screen_rect.origin.y -= y_offset;

  // Apply a scale and translate to keep the window centered.
  screen_rect.origin.x += (NSWidth(win_rect) - NSWidth(screen_rect)) / 2.0;
  screen_rect.origin.y += (NSHeight(win_rect) - NSHeight(screen_rect)) / 2.0;

  // A 2 x 2 mesh that maps each corner of the window to a location in screen
  // coordinates. Note that the origin of the coordinate system is top, left.
  CGPointWarp mesh[2][2] = {
      {{
        // Top left.
        {NSMinX(win_rect), NSMinY(win_rect)},
        {NSMinX(screen_rect) + perspective_offset, NSMinY(screen_rect)},
       },
       {
        // Top right.
        {NSMaxX(win_rect), NSMinY(win_rect)},
        {NSMaxX(screen_rect) - perspective_offset, NSMinY(screen_rect)}, }},
      {{
        // Bottom left.
        {NSMinX(win_rect), NSMaxY(win_rect)},
        {NSMinX(screen_rect), NSMaxY(screen_rect)},
       },
       {
        // Bottom right.
        {NSMaxX(win_rect), NSMaxY(win_rect)},
        {NSMaxX(screen_rect), NSMaxY(screen_rect)}, }},
  };

  CGSConnection cid = _CGSDefaultConnection();
  CGSSetWindowWarp(cid, [window windowNumber], 2, 2, &(mesh[0][0]));
}

// Sets the various effects that are a part of the Show/Hide animation.
// Value is a number between 0 and 1 where 0 means the window is completely
// hidden and 1 means the window is fully visible.
void UpdateWindowShowHideAnimationState(NSWindow* window, CGFloat value) {
  CGFloat inverse_value = 1.0 - value;

  SetWindowAlpha(window, value);
  CGFloat y_offset = kShowHideVerticalOffset * inverse_value;
  CGFloat scale = 1.0 - (1.0 - kShowHideScaleFactor) * inverse_value;
  CGFloat perspective_offset =
      ([window frame].size.width * kShowHidePerspectiveFactor) * inverse_value;

  SetWindowWarp(window, y_offset, scale, perspective_offset);
}

bool AreWindowServerEffectsDisabled() {
  // If the CHROME_HEADLESS env variable is set, this code is running in a
  // test environment. The custom constrained window animations may be
  // causing the WindowServer to crash (https://crbug.com/828031), so use the
  // simple animations.
  static bool is_headless = getenv("CHROME_HEADLESS") != nullptr;
  return is_headless;
}

}  // namespace

@interface ConstrainedWindowAnimationBase ()
// Subclasses should override these to update the window state for the current
// animation value.
- (void)setWindowStateForStart;
- (void)setWindowStateForValue:(float)value;
- (void)setWindowStateForEnd;
@end

@implementation ConstrainedWindowAnimationBase

- (instancetype)initWithWindow:(NSWindow*)window {
  if ((self = [self initWithDuration:kAnimationDuration
                      animationCurve:NSAnimationEaseInOut])) {
    window_.reset([window retain]);
    [self setAnimationBlockingMode:NSAnimationBlocking];
    [self setWindowStateForStart];
  }
  return self;
}

- (void)stopAnimation {
  [super stopAnimation];
  [self setWindowStateForEnd];
  if ([[self delegate] respondsToSelector:@selector(animationDidEnd:)])
    [[self delegate] animationDidEnd:self];
}

- (void)setCurrentProgress:(NSAnimationProgress)progress {
  [super setCurrentProgress:progress];

  if (progress >= 1.0) {
    [self setWindowStateForEnd];

    // Starting in 10.10, the WindowServer forgets to draw the shadow on windows
    // that animate in this way on retina screens. -[NSWindow invalidateShadow]
    // doesn't fix it. Neither does toggling -setHasShadow:. But forcing an
    // update to the window size, and then undoing it, seems to fix the problem.
    // See http://crbug.com/436884.
    // TODO(tapted): Find a better fix (this is horrible).
    NSRect frame = [window_ frame];
    [window_ setFrame:NSInsetRect(frame, 1, 1) display:NO animate:NO];
    [window_ setFrame:frame display:NO animate:NO];
    return;
  }
  [self setWindowStateForValue:[self currentValue]];
}

- (void)setWindowStateForStart {
  // Subclasses can optionally override this method.
}

- (void)setWindowStateForValue:(float)value {
  // Subclasses must override this method.
  NOTREACHED();
}

- (void)setWindowStateForEnd {
  // Subclasses can optionally override this method.
}

@end

@implementation ConstrainedWindowAnimationShow

- (void)setWindowStateForStart {
  if (AreWindowServerEffectsDisabled()) {
    [window_ setAlphaValue:0.0];
    return;
  }
  SetWindowAlpha(window_, 0.0);
}

- (void)setWindowStateForValue:(float)value {
  if (AreWindowServerEffectsDisabled()) {
    [window_ setAlphaValue:value];
    return;
  }
  UpdateWindowShowHideAnimationState(window_, value);
}

- (void)setWindowStateForEnd {
  if (AreWindowServerEffectsDisabled()) {
    [window_ setAlphaValue:1.0];
    return;
  }
  SetWindowAlpha(window_, 1.0);
  ClearWindowWarp(window_);
}

@end

@implementation ConstrainedWindowAnimationHide

- (void)setWindowStateForValue:(float)value {
  if (AreWindowServerEffectsDisabled()) {
    [window_ setAlphaValue:1.0 - value];
    return;
  }
  UpdateWindowShowHideAnimationState(window_, 1.0 - value);
}

- (void)setWindowStateForEnd {
  if (AreWindowServerEffectsDisabled()) {
    [window_ setAlphaValue:0.0];
    return;
  }
  SetWindowAlpha(window_, 0.0);
  ClearWindowWarp(window_);
}

@end

@implementation ConstrainedWindowAnimationPulse

// Sets the window scale based on the animation progress.
- (void)setWindowStateForValue:(float)value {
  if (AreWindowServerEffectsDisabled())
    return;

  KeyFrame frames[] = {
      {0.00, 1.0}, {0.40, 1.02}, {0.60, 1.02}, {1.00, 1.0},
  };

  CGFloat scale = 1;
  for (int i = base::size(frames) - 1; i >= 0; --i) {
    if (value >= frames[i].value) {
      CGFloat delta = frames[i + 1].value - frames[i].value;
      CGFloat frame_progress = (value - frames[i].value) / delta;
      scale = gfx::Tween::FloatValueBetween(frame_progress, frames[i].scale,
                                            frames[i + 1].scale);
      break;
    }
  }

  SetWindowScale(window_, scale);
}

- (void)setWindowStateForEnd {
  if (AreWindowServerEffectsDisabled()) {
    NSBeep();
    return;
  }

  SetWindowScale(window_, 1.0);
}

@end
