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

class Locker<TKey> {
  final _keyQueue = Queue<TKey>();
  final _completerMap = <TKey, Completer<bool>>{};
  TKey? _currKey;
  bool _isRunning = false;

  Future<bool> lock(TKey uniqueKey) async {
    final complete = Completer<bool>();
    _completerMap[uniqueKey] = complete;
    _keyQueue.addLast(uniqueKey);
    Future.delayed(const Duration(milliseconds: 10), () {
      _run();
    });
    final result = await complete.future;
    if (result) {
      // 成功锁定
      _currKey = uniqueKey;
      print("🧨🧨🧨Locker locked!!!! key: $uniqueKey");
    }
    return result;
  }

  // 解锁
  void unlock(TKey uniqueKey) {
    if (_completerMap.containsKey(uniqueKey)) {
      // 此Key正在排队等待加锁，取消排队
      final complete = _completerMap.remove(uniqueKey)!;
      complete.complete(false); // 通知锁定失败
      _keyQueue.remove(uniqueKey);
    }

    if (uniqueKey == _currKey) {
      // 当前锁持有者才能解锁
      _currKey = null;
      print("🧨🧨🧨Locker unlocked!!!! key: $uniqueKey");
    }
  }

  void _run() async {
    if (_isRunning) {
      return;
    }

    _isRunning = true;
    while (_keyQueue.isNotEmpty) {
      if (_currKey == null) {
        final key = _keyQueue.removeFirst();
        _currKey = key; // 锁定
        final completer = _completerMap.remove(key);
        completer!.complete(true); // 通知锁定成功
      }

      // 间隔10ms
      await Future.delayed(const Duration(milliseconds: 10));
    }
    _isRunning = false;
  }
}
