import 'dart:async';

import 'package:flutter/material.dart';

import '../../../../../widget/app_progress_indicator.dart';
import 'loadable_state_consumer.dart';

/// Full-screen spinner for the initial load. A minutes-long spinner without
/// feedback looks stuck (the Nextcloud root listing can take that long), so
/// after [slowHintAfter] a generic slow-server note fades in below it. An
/// explicit [statusText] (e.g. retry progress from the bloc) always takes
/// precedence over the timer-based hint.
class LoadableStatePrimaryLoading extends StatefulWidget {
  final bool visible;
  final String? statusText;
  final Duration slowHintAfter;

  const LoadableStatePrimaryLoading({
    required this.visible,
    this.statusText,
    this.slowHintAfter = const Duration(seconds: 8),
    super.key,
  });

  static const String slowHintText = 'Der Server antwortet verzögert …';

  @override
  State<LoadableStatePrimaryLoading> createState() =>
      _LoadableStatePrimaryLoadingState();
}

class _LoadableStatePrimaryLoadingState
    extends State<LoadableStatePrimaryLoading> {
  Timer? _slowHintTimer;
  bool _showSlowHint = false;

  @override
  void initState() {
    super.initState();
    _restartSlowHintTimer();
  }

  @override
  void didUpdateWidget(covariant LoadableStatePrimaryLoading oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (widget.visible != oldWidget.visible) _restartSlowHintTimer();
  }

  void _restartSlowHintTimer() {
    _slowHintTimer?.cancel();
    _showSlowHint = false;
    if (!widget.visible) return;
    _slowHintTimer = Timer(widget.slowHintAfter, () {
      if (mounted) setState(() => _showSlowHint = true);
    });
  }

  @override
  void dispose() {
    _slowHintTimer?.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final status =
        widget.statusText ??
        (_showSlowHint ? LoadableStatePrimaryLoading.slowHintText : null);

    return AnimatedOpacity(
      opacity: widget.visible ? 1.0 : 0.0,
      duration: LoadableStateConsumer.animationDuration,
      curve: Curves.easeInOut,
      child: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            const AppProgressIndicator.large(),
            AnimatedSwitcher(
              duration: LoadableStateConsumer.animationDuration,
              child: status == null
                  ? const SizedBox.shrink()
                  : Padding(
                      key: ValueKey(status),
                      padding: const EdgeInsets.only(
                        top: 16,
                        left: 24,
                        right: 24,
                      ),
                      child: Text(
                        status,
                        textAlign: TextAlign.center,
                        style: TextStyle(
                          fontSize: 13,
                          color: Theme.of(context).hintColor,
                        ),
                      ),
                    ),
            ),
          ],
        ),
      ),
    );
  }
}
