import 'dart:async';
import 'dart:collection';

import 'package:flutter/foundation.dart';

import 'enums.dart';

/// A controller that can be used to trigger swipes on a CardSwiper widget.
class CardSwiperController extends ChangeNotifier {
  CardSwiperState? state;
  final StreamController<int> _controller = StreamController.broadcast();
  final Queue<(CardSwiperDirection, String)> directionHistory = Queue();

  int currentIndex = 0;

  CardSwiperController() {}

  Set<String> get swipedLeftIds => directionHistory
      .where((element) => element.$1 == CardSwiperDirection.left)
      .map((e) => e.$2)
      .toSet();

  Set<String> get swipedRightIds => directionHistory
      .where((element) => element.$1 == CardSwiperDirection.right)
      .map((e) => e.$2)
      .toSet();

  int get progress => directionHistory.length;

  void setIndex(int index) {
    currentIndex = index;
    _controller.add(index);
  }

  @override
  Future<void> dispose() async {
    super.dispose();
  }

  /// Swipe the card by changing the status of the controller
  void swipe({CardSwiperState? direction}) {
    state = direction ?? CardSwiperState.swipeLeft;
    notifyListeners();
  }

  void swipedLeft() {
    directionHistory.add((CardSwiperDirection.left, currentIndex.toString()));
    // notifyListeners();
  }

  void swipedRight() {
    directionHistory.add((CardSwiperDirection.right, currentIndex.toString()));
    // notifyListeners();
  }

  /// Swipe the card to the top side by changing the status of the controller
  void swipeTop() {
    state = CardSwiperState.swipeTop;
    notifyListeners();
  }

  /// Swipe the card to the bottom side by changing the status of the controller
  void swipeBottom() {
    state = CardSwiperState.swipeBottom;
    notifyListeners();
  }

  // Undo the last swipe by changing the status of the controller
  void undo() {
    state = CardSwiperState.undo;
    notifyListeners();
  }

  void restart() {
    state = CardSwiperState.restart;
    notifyListeners();
  }

  Stream<int> get asStream => _controller.stream.distinct();
}
