// 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 '../logic/card.dart' as logic_card;

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;

enum CardAnimationType { NONE, OLD_TO_NEW, IN_TOP }

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 bool animateEntrance;
  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,
        animateEntrance = dataComponent.animateEntrance,
        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 bool animateEntrance;
  final double z;

  Card(logic_card.Card card, this.faceUp,
      {double width,
      double height,
      this.rotation: 0.0,
      bool useKey: false,
      this.visible: true,
      this.animateEntrance: true,
      this.z})
      : 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,
        animateEntrance: false,
        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.animateEntrance == animateEntrance && 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;
  bool _cardUpdateScheduled = false;

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

  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: const Duration(milliseconds: 250));
    _performance.addStatusListener((PerformanceStatus status) {
      if (status == PerformanceStatus.completed) {
        _animationIndex++;
        _tryAnimate();
      }
    });
  }

  void scheduleUpdatePosition() {
    if (!_cardUpdateScheduled) {
      _cardUpdateScheduled = true;
      scheduleMicrotask(_updatePosition);
    }
  }

  // These microtasks are being scheduled on every build change.
  // Theoretically, this is too often, but to be safe, it is also good to do it.
  @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();
        });
      }
    }
    scheduleUpdatePosition();
  }

  // A callback that sets up the animation from point a to point b.
  void _updatePosition() {
    _cardUpdateScheduled =
        false; // allow the next attempt to schedule _updatePosition to succeed.
    if (!config.animateEntrance || _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;
  }

  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.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;
  }
}
