// Copyright 2015 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 'dart:math' as math;
import 'dart:sky' as sky;

import 'package:vector_math/vector_math.dart';

import '../framework/animation/animated_value.dart';
import '../framework/animation/curves.dart';
import '../theme2/colors.dart';
import '../theme2/shadows.dart';
import 'animated_component.dart';
import 'basic.dart';

// TODO(eseidel): Draw width should vary based on device size:
// http://www.google.com/design/spec/layout/structure.html#structure-side-nav

// Mobile:
// Width = Screen width − 56 dp
// Maximum width: 320dp
// Maximum width applies only when using a left nav. When using a right nav,
// the panel can cover the full width of the screen.

// Desktop/Tablet:
// Maximum width for a left nav is 400dp.
// The right nav can vary depending on content.

const double _kWidth = 304.0;
const double _kMinFlingVelocity = 0.4;
const double _kBaseSettleDurationMS = 246.0;
const double _kMaxSettleDurationMS = 600.0;
const Curve _kAnimationCurve = parabolicRise;

typedef void DrawerStatusChangeHandler (bool showing);

class DrawerController {

  DrawerController(this.onStatusChange) {
    position = new AnimatedValue(-_kWidth, onChange: _checkValue);
  }
  final DrawerStatusChangeHandler onStatusChange;
  AnimatedValue position;

  bool _oldClosedState = true;
  void _checkValue() {
    var newClosedState = isClosed;
    if (onStatusChange != null && _oldClosedState != newClosedState) {
      onStatusChange(!newClosedState);
      _oldClosedState = newClosedState;
    }
  }

  bool get isClosed => position.value == -_kWidth;
  bool get _isMostlyClosed => position.value <= -_kWidth / 2;
  void toggle() => _isMostlyClosed ? _open() : _close();

  void handleMaskTap(_) => _close();
  void handlePointerDown(_) => position.stop();

  void handlePointerMove(sky.PointerEvent event) {
    if (position.isAnimating)
      return;
    position.value = math.min(0.0, math.max(position.value + event.dx, -_kWidth));
  }

  void handlePointerUp(_) {
    if (!position.isAnimating)
      _settle();
  }

  void handlePointerCancel(_) {
    if (!position.isAnimating)
      _settle();
  }

  void _open() => _animateToPosition(0.0);

  void _close() => _animateToPosition(-_kWidth);

  void _settle() => _isMostlyClosed ? _close() : _open();

  void _animateToPosition(double targetPosition) {
    double distance = (targetPosition - position.value).abs();
    if (distance != 0) {
      double targetDuration = distance / _kWidth * _kBaseSettleDurationMS;
      double duration = math.min(targetDuration, _kMaxSettleDurationMS);
      position.animateTo(targetPosition, duration, curve: _kAnimationCurve);
    }
  }

  void handleFlingStart(event) {
    double direction = event.velocityX.sign;
    double velocityX = event.velocityX.abs() / 1000;
    if (velocityX < _kMinFlingVelocity)
      return;

    double targetPosition = direction < 0.0 ? -_kWidth : 0.0;
    double distance = (targetPosition - position.value).abs();
    double duration = distance / velocityX;

    if (distance > 0)
      position.animateTo(targetPosition, duration, curve: linear);
  }

}

class Drawer extends AnimatedComponent {

  Drawer({
    String key,
    this.controller,
    this.children,
    this.level: 0
  }) : super(key: key) {
    animate(controller.position, (double value) {
      _position = value;
    });
  }

  List<Widget> children;
  int level;
  DrawerController controller;

  void syncFields(Drawer source) {
    children = source.children;
    level = source.level;
    controller = source.controller;
    super.syncFields(source);
  }

  double _position;

  Widget build() {
    Matrix4 transform = new Matrix4.identity();
    transform.translate(_position);

    double scaler = _position / _kWidth + 1;
    Color maskColor = new Color.fromARGB((0x7F * scaler).floor(), 0, 0, 0);

    var mask = new Listener(
      child: new Container(decoration: new BoxDecoration(backgroundColor: maskColor)),
      onGestureTap: controller.handleMaskTap,
      onGestureFlingStart: controller.handleFlingStart
    );

    Container content = new Container(
      decoration: new BoxDecoration(
        backgroundColor: Grey[50],
        boxShadow: shadows[level]),
      width: _kWidth,
      transform: transform,
      child: new Block(children)
    );

    return new Listener(
      child: new Stack([ mask, content ]),
      onPointerDown: controller.handlePointerDown,
      onPointerMove: controller.handlePointerMove,
      onPointerUp: controller.handlePointerUp,
      onPointerCancel: controller.handlePointerCancel
    );
  }

}
