// Copyright 2015 The Vanadium 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:async';

import 'package:flutter/animation.dart';
import 'package:flutter/material.dart' as widgets;
import 'package:flutter/rendering.dart';
import 'package:vector_math/vector_math_64.dart' as vector_math;

import '../logic/card.dart' as logic_card;

enum CardAnimationType { NONE, NORMAL, LONG }

enum CardUIType { CARD, ZCARD }

class GlobalCardKey extends widgets.GlobalKey {
  logic_card.Card card;
  CardUIType type;

  GlobalCardKey(this.card, this.type) : super.constructor();

  bool operator ==(Object other) {
    if (other is! GlobalCardKey) {
      return false;
    }
    GlobalCardKey k = other;
    return k.card == card && k.type == type;
  }

  int get hashCode {
    return 17 * card.hashCode + 33 * type.hashCode;
  }
}

class ZCard extends widgets.StatefulComponent {
  final logic_card.Card card;
  final bool faceUp;
  final double width;
  final double height;
  final double rotation;
  final CardAnimationType animationType;
  final double z;

  // These points are in local coordinates.
  final Point startingPosition;
  final Point endingPosition;

  ZCard(Card dataComponent, this.startingPosition, this.endingPosition)
      : super(key: new GlobalCardKey(dataComponent.card, CardUIType.ZCARD)),
        card = dataComponent.card,
        faceUp = dataComponent.faceUp,
        width = dataComponent.width ?? 40.0,
        height = dataComponent.height ?? 40.0,
        rotation = dataComponent.rotation,
        animationType = dataComponent.animationType,
        z = dataComponent.z;

  ZCardState createState() => new ZCardState();
}

class Card extends widgets.StatefulComponent {
  final logic_card.Card card;
  final bool faceUp;
  final double width;
  final double height;
  final double rotation;
  final bool useKey;
  final bool visible;
  final CardAnimationType animationType;
  final double z;

  Card(logic_card.Card card, this.faceUp,
      {double width,
      double height,
      this.rotation: 0.0,
      bool useKey: false,
      this.visible: true,
      CardAnimationType animationType,
      this.z})
      : animationType = animationType ?? CardAnimationType.NONE,
        card = card,
        width = width ?? 40.0,
        height = height ?? 40.0,
        useKey = useKey,
        super(key: useKey ? new GlobalCardKey(card, CardUIType.CARD) : null);

  // Use this helper to help create a Card clone.
  // Used by the drag and drop layer.
  Card clone({bool visible}) {
    return new Card(this.card, this.faceUp,
        width: width,
        height: height,
        rotation: rotation,
        useKey: false,
        visible: visible ?? this.visible,
        animationType: CardAnimationType.NONE,
        z: z);
  }

  // Check if the data between these Cards matches.
  // This isn't == since I don't want to override that and hashCode.
  bool isMatchWith(Card c) {
    return c.card == card &&
        c.faceUp == faceUp &&
        c.width == width &&
        c.height == height &&
        c.rotation == rotation &&
        c.useKey == useKey &&
        c.visible == visible &&
        c.animationType == animationType &&
        c.z == z;
  }

  CardState createState() => new CardState();
}

class CardState extends widgets.State<Card> {
  // TODO(alexfandrianto): This bug is why some cards appear slightly off.
  // https://github.com/flutter/engine/issues/1939
  Point getGlobalPosition() {
    RenderBox box = context.findRenderObject();
    return box.localToGlobal(Point.origin);
  }

  widgets.Widget build(widgets.BuildContext context) {
    widgets.Widget image = new widgets.Opacity(
        opacity: config.visible ? 1.0 : 0.0,
        child: new widgets.Transform(
            child: _imageFromCard(
                config.card, config.faceUp, config.width, config.height),
            transform:
                new vector_math.Matrix4.identity().rotateZ(config.rotation),
            alignment: new FractionalOffset(0.5, 0.5)));

    return image;
  }
}

widgets.Widget _imageFromCard(
    logic_card.Card c, bool faceUp, double width, double height) {
  // TODO(alexfandrianto): Instead of 'default', what if we were told which theme to use?
  String imageName =
      "images/default/${c.deck}/${faceUp ? 'up' : 'down'}/${c.identifier}.png";
  return new widgets.AssetImage(name: imageName, width: width, height: height);
}

class ZCardState extends widgets.State<ZCard> {
  ValuePerformance<Point> _performance;
  List<
      Point> _pointQueue; // at least 1 longer than the current animation index.
  int _animationIndex;

  @override
  void initState() {
    super.initState();
    _initialize();
    _updatePosition();
  }

  void _initialize() {
    _pointQueue = new List<Point>();
    _animationIndex = 0;
    if (config.startingPosition != null) {
      _pointQueue.add(config.startingPosition);
    }
    _pointQueue.add(config.endingPosition);
    _performance = new ValuePerformance<Point>(
        variable: new AnimatedValue<Point>(Point.origin, curve: Curves.ease),
        duration: this.animationDuration);
    _performance.addStatusListener((PerformanceStatus status) {
      if (status == PerformanceStatus.completed) {
        _animationIndex++;
        _tryAnimate();
      }
    });
  }

  Duration get animationDuration {
    switch (config.animationType) {
      case CardAnimationType.NONE:
        return const Duration(milliseconds: 0);
      case CardAnimationType.NORMAL:
        return const Duration(milliseconds: 250);
      case CardAnimationType.LONG:
        return const Duration(milliseconds: 750);
      default:
        print("Unexpected animation type: ${config.animationType}");
        assert(false);
        return null;
    }
  }

  @override
  void didUpdateConfig(ZCard oldConfig) {
    if (config.key != oldConfig.key) {
      _initialize();
    } else {
      // Do we need to animate to a new location? If so, add it to the queue.
      if (config.endingPosition != _pointQueue.last) {
        setState(() {
          _pointQueue.add(config.endingPosition);
          _tryAnimate();
        });
      }
    }
    _updatePosition();
  }

  // A callback that sets up the animation from point a to point b.
  void _updatePosition() {
    if (config.animationType == CardAnimationType.NONE ||
        _pointQueue.length == 1) {
      Point endingLocation = config.endingPosition;
      _performance.variable
        ..begin = endingLocation
        ..value = endingLocation
        ..end = endingLocation;
      _performance.progress = 0.0;
      return;
    }

    _tryAnimate();
  }

  bool _needsAnimation() {
    return _animationIndex < _pointQueue.length - 1;
  }

  // Return the current animation position of the ZCard.
  Point get localPosition {
    return _performance.variable.value;
  }

  void _tryAnimate() {
    // Let animations finish... (Is this a good idea?)
    if (!_performance.isAnimating && _needsAnimation()) {
      Point startingLocation = _pointQueue[_animationIndex];
      Point endingLocation = _pointQueue[_animationIndex + 1];
      _performance.variable
        ..begin = startingLocation
        ..value = startingLocation
        ..end = endingLocation;
      _performance.progress = 0.0;
      _performance.duration = this.animationDuration;
      _performance.play();
    }
  }

  widgets.Widget build(widgets.BuildContext context) {
    widgets.Widget image = new widgets.Transform(
        child: _imageFromCard(
            config.card, config.faceUp, config.width, config.height),
        transform: new vector_math.Matrix4.identity().rotateZ(config.rotation),
        alignment: new FractionalOffset(0.5, 0.5));

    // Set up the slide transition.
    // During animation, we must ignore all events.
    widgets.Widget retWidget = new widgets.SlideTransition(
        performance: _performance.view,
        position: _performance.variable,
        child: image);

    return retWidget;
  }
}
