// SPDX-FileCopyrightText: 2019-Present Christian Kußowski
// SPDX-FileCopyrightText: 2019-Present Contributors to FluffyChat
//
// SPDX-License-Identifier: AGPL-3.0-or-later

import 'dart:math';

import 'package:fluffychat/config/setting_keys.dart';
import 'package:fluffychat/l10n/l10n.dart';
import 'package:flutter/material.dart';
import 'package:matrix/matrix.dart';

class CuteContent extends StatefulWidget {
  final Event event;

  const CuteContent(this.event, {super.key});

  @override
  State<CuteContent> createState() => _CuteContentState();
}

class _CuteContentState extends State<CuteContent> {
  static bool _isOverlayShown = false;

  @override
  void initState() {
    if (AppSettings.autoplayImages.value && !_isOverlayShown) {
      addOverlay();
    }
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<User?>(
      future: widget.event.fetchSenderUser(),
      builder: (context, snapshot) {
        final label = generateLabel(snapshot.data);

        return GestureDetector(
          onTap: addOverlay,
          child: Column(
            mainAxisSize: .min,
            mainAxisAlignment: .center,
            children: [
              Text(widget.event.text, style: const TextStyle(fontSize: 150)),
              if (label != null) Text(label),
            ],
          ),
        );
      },
    );
  }

  Future<void> addOverlay() async {
    _isOverlayShown = true;
    await Future.delayed(const Duration(milliseconds: 50));
    if (!mounted) return;

    OverlayEntry? overlay;
    overlay = OverlayEntry(
      builder: (context) => CuteEventOverlay(
        emoji: widget.event.text,
        onAnimationEnd: () {
          _isOverlayShown = false;
          overlay?.remove();
        },
      ),
    );
    Overlay.of(context).insert(overlay);
  }

  String? generateLabel(User? user) {
    switch (widget.event.content['cute_type']) {
      case 'googly_eyes':
        return L10n.of(context).googlyEyesContent(
          user?.displayName ??
              widget.event.senderFromMemoryOrFallback.displayName ??
              '',
        );
      case 'cuddle':
        return L10n.of(context).cuddleContent(
          user?.displayName ??
              widget.event.senderFromMemoryOrFallback.displayName ??
              '',
        );
      case 'hug':
        return L10n.of(context).hugContent(
          user?.displayName ??
              widget.event.senderFromMemoryOrFallback.displayName ??
              '',
        );
    }
    return null;
  }
}

class CuteEventOverlay extends StatefulWidget {
  final String emoji;
  final VoidCallback onAnimationEnd;

  const CuteEventOverlay({
    super.key,
    required this.emoji,
    required this.onAnimationEnd,
  });

  @override
  State<CuteEventOverlay> createState() => _CuteEventOverlayState();
}

class _CuteEventOverlayState extends State<CuteEventOverlay>
    with TickerProviderStateMixin {
  final List<Size> items = List.generate(
    50,
    (index) => Size(Random().nextDouble(), 4 + (Random().nextDouble() * 4)),
  );

  AnimationController? controller;

  @override
  void initState() {
    controller = AnimationController(
      duration: const Duration(milliseconds: 2500),
      vsync: this,
    );
    controller?.forward();
    controller?.addStatusListener(_hideOverlay);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: controller!,
      builder: (context, _) => LayoutBuilder(
        builder: (context, constraints) {
          final width = constraints.maxWidth - _CuteOverlayContent.size;
          final height = constraints.maxHeight + _CuteOverlayContent.size;
          return SizedBox(
            height: constraints.maxHeight,
            width: constraints.maxWidth,
            child: OverflowBox(
              child: Stack(
                alignment: Alignment.bottomLeft,
                fit: StackFit.expand,
                children: items
                    .map(
                      (position) => Positioned(
                        left: position.width * width,
                        bottom:
                            (height *
                                .25 *
                                position.height *
                                (controller?.value ?? 0)) -
                            _CuteOverlayContent.size,
                        child: _CuteOverlayContent(emoji: widget.emoji),
                      ),
                    )
                    .toList(),
              ),
            ),
          );
        },
      ),
    );
  }

  void _hideOverlay(AnimationStatus status) {
    if (status == AnimationStatus.completed) {
      widget.onAnimationEnd.call();
    }
  }
}

class _CuteOverlayContent extends StatelessWidget {
  static const double size = 64.0;
  final String emoji;

  const _CuteOverlayContent({required this.emoji});

  @override
  Widget build(BuildContext context) {
    return SizedBox.square(
      dimension: size,
      child: Text(emoji, style: const TextStyle(fontSize: 48)),
    );
  }
}
