import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class AnimatedSwitcherWidget extends StatefulWidget {
  final SwitcherController controller;
  final Duration duration;

  const AnimatedSwitcherWidget({
    super.key,
    required this.controller,
    this.duration = const Duration(milliseconds: 1500),
  });

  @override
  State<AnimatedSwitcherWidget> createState() => _AnimatedSwitcherWidgetState();
}

class _AnimatedSwitcherWidgetState extends State<AnimatedSwitcherWidget> {
  Widget? _currentWidget;

  @override
  void initState() {
    super.initState();
    // 注册更新回调
    widget.controller._registerOnUpdate(() => setState(() {
          _currentWidget = widget.controller._currentWidget;
        }));
  }

  @override
  Widget build(BuildContext context) {
    return ClipRRect(
      child: AnimatedSwitcher(
        duration: widget.duration,
        transitionBuilder: (Widget child, Animation<double> animation) {
          return SlideTransitionX(
            direction: AxisDirection.down,
            position: animation,
            child: child,
          );
        },
        child: Center(key: ValueKey(_currentWidget), child: _currentWidget),
      ),
    );
  }
}

class SwitcherController {
  // 保存当前组件和回调函数
  Widget? _currentWidget;
  VoidCallback? _onUpdate;

  // 更新组件并触发回调
  void updateWidget(Widget newWidget) {
    _currentWidget = newWidget;
    _onUpdate?.call();
  }

  // 注册更新回调（供State内部调用）
  void _registerOnUpdate(VoidCallback onUpdate) {
    _onUpdate = onUpdate;
  }
}

class SlideTransitionX extends AnimatedWidget {
  SlideTransitionX({
    super.key,
    required Animation<double> position,
    this.transformHitTests = true,
    this.direction = AxisDirection.down,
    required this.child,
  }) : super(listenable: position) {
    switch (direction) {
      case AxisDirection.up:
        _tween = Tween(begin: const Offset(0, 1), end: const Offset(0, 0));
        break;
      case AxisDirection.right:
        _tween = Tween(begin: const Offset(-1, 0), end: const Offset(0, 0));
        break;
      case AxisDirection.down:
        _tween = Tween(begin: const Offset(0, -1), end: const Offset(0, 0));
        break;
      case AxisDirection.left:
        _tween = Tween(begin: const Offset(1, 0), end: const Offset(0, 0));
        break;
    }
  }

  final bool transformHitTests;

  final Widget child;

  final AxisDirection direction;

  late final Tween<Offset> _tween;

  @override
  Widget build(BuildContext context) {
    final position = listenable as Animation<double>;
    Offset offset = _tween.evaluate(position);
    if (position.status == AnimationStatus.reverse) {
      switch (direction) {
        case AxisDirection.up:
          offset = Offset(offset.dx, -offset.dy);
          break;
        case AxisDirection.right:
          offset = Offset(-offset.dx, offset.dy);
          break;
        case AxisDirection.down:
          offset = Offset(offset.dx, -offset.dy);
          break;
        case AxisDirection.left:
          offset = Offset(-offset.dx, offset.dy);
          break;
      }
    }
    return FractionalTranslation(
      translation: offset,
      transformHitTests: transformHitTests,
      child: child,
    );
  }
}
