import 'dart:math';

import 'package:extended_image/extended_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:loading_animation_widget/loading_animation_widget.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart';
import 'package:tencent_cloud_chat_uikit/ui/widgets/gestured_image.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
import 'package:tencent_cloud_chat_uikit/ui/widgets/image_hero.dart';

typedef DoubleClickAnimationListener = void Function();

class ImageScreen extends StatefulWidget {
  const ImageScreen(
      {required this.imageProvider,
      required this.heroTag,
      this.downloadFn,
      this.messageID,
      Key? key})
      : super(key: key);

  final ImageProvider imageProvider;
  final String heroTag;
  final String? messageID;
  final Future<void> Function()? downloadFn;

  @override
  State<StatefulWidget> createState() {
    return _ImageScreenState();
  }
}

class _ImageScreenState extends TIMUIKitState<ImageScreen>
    with TickerProviderStateMixin {
  Animation<double>? _doubleClickAnimation;
  late DoubleClickAnimationListener _doubleClickAnimationListener;
  late AnimationController _doubleClickAnimationController;
  List<double> doubleTapScales = <double>[1.0, 2.0];
  double currentScale = 1.0;
  double fittedScale = 1.0;
  double initialScale = 1.0;
  bool isLoading = false;

  GlobalKey<ExtendedImageSlidePageState> slidePageKey =
      GlobalKey<ExtendedImageSlidePageState>();
  GlobalKey<ExtendedImageGestureState> extendedImageGestureKey =
      GlobalKey<ExtendedImageGestureState>();

  void close() {
    slidePageKey.currentState!.popPage();
    Navigator.pop(context);
  }

  @override
  void initState() {
    super.initState();
    // 允许横屏
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.landscapeLeft,
      DeviceOrientation.landscapeRight,
      DeviceOrientation.portraitUp,
      DeviceOrientation.portraitDown,
    ]);
    _doubleClickAnimationController = AnimationController(
        duration: const Duration(milliseconds: 150), vsync: this);
  }

  @override
  void dispose() {
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp,
    ]);
    _doubleClickAnimationController.dispose();
    super.dispose();
  }

  @override
  Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
    return OrientationBuilder(builder: ((context, orientation) {
      if (extendedImageGestureKey.currentState != null) {
        extendedImageGestureKey.currentState!.reset();
      }

      return Material(
        color: Colors.transparent,
        child: Container(
            color: Colors.transparent,
            constraints: BoxConstraints.expand(
              height: MediaQuery.of(context).size.height,
            ),
            child: Stack(
              alignment: Alignment.center,
                children: [
              Positioned(
                top: 0,
                left: 0,
                bottom: 0,
                right: 0,
                child: ExtendedImageSlidePage(
                  key: slidePageKey,
                  slideAxis: SlideAxis.both,
                  slidePageBackgroundHandler: (Offset offset, Size size) {
                    if (orientation == Orientation.landscape) {
                      return Colors.black;
                    }
                    double opacity = 0.0;
                    opacity = offset.distance /
                        (Offset(size.width, size.height).distance / 2.0);
                    return Colors.black
                        .withOpacity(min(1.0, max(1.0 - opacity, 0.0)));
                  },
                  slideType: SlideType.onlyImage,
                  slideEndHandler: (
                    Offset offset, {
                    ExtendedImageSlidePageState? state,
                    ScaleEndDetails? details,
                  }) {
                    final vy = details?.velocity.pixelsPerSecond.dy ?? 0;
                    final oy = offset.dy;
                    if (vy > 300 || oy > 100) {
                      return true;
                    }
                    return null;
                  },
                  child: GestureDetector(
                    onTap: close,
                    child: HeroWidget(
                        tag: widget.heroTag,
                        slidePagekey: slidePageKey,
                        child: ExtendedImage(
                          image: widget.imageProvider,
                          extendedImageGestureKey:
                          extendedImageGestureKey,
                          enableSlideOutPage: true,
                          // fit: BoxFit.scaleDown,
                          initGestureConfigHandler: (state) {
                            return GestureConfig(
                              minScale: 0.8,
                              animationMinScale: 0.6,
                              maxScale: 2 * fittedScale,
                              animationMaxScale: 2.5 * fittedScale,
                              speed: 1.0,
                              inertialSpeed: 100.0,
                              initialScale: initialScale,
                              initialAlignment:
                              InitialAlignment.topCenter,
                              hitTestBehavior: HitTestBehavior.opaque,
                            );
                          },
                          loadStateChanged: (ExtendedImageState state) {
                            switch (state.extendedImageLoadState) {
                              case LoadState.loading:
                                return Container(
                                    color: Colors.black,
                                    child: const Center(
                                        child: CircularProgressIndicator(
                                            color: Colors.white))
                                );
                              case LoadState.completed:
                                final screenHeight =
                                    MediaQuery.of(context).size.height;
                                final screenWidth =
                                    MediaQuery.of(context).size.width;
                                final imgHeight = state.extendedImageInfo
                                    ?.image.height ??
                                    1;
                                final imgWidth = state
                                    .extendedImageInfo?.image.width ??
                                    0;
                                final imgRatio = imgWidth / imgHeight;
                                final screenRatio =
                                    screenWidth / screenHeight;
                                final fitWidthScale =
                                    screenRatio / imgRatio;
                                if (screenRatio > imgRatio) {
                                  // Long Image
                                  // initialScale = fitWidthScale;
                                  fittedScale = fitWidthScale;
                                  doubleTapScales[1] = fitWidthScale;
                                } else {
                                  fittedScale =
                                      1 / fitWidthScale; // fittedHeight
                                  doubleTapScales[1] = 1 / fitWidthScale;
                                }

                                return GesturedImage(state,
                                    key: extendedImageGestureKey);
                              case LoadState.failed:
                                break;
                            }
                            return null;
                          },
                          onDoubleTap: (ExtendedImageGestureState state) {
                            ///you can use define pointerDownPosition as you can,
                            ///default value is double tap pointer down position.
                            final Offset? pointerDownPosition =
                                state.pointerDownPosition;
                            final double? begin =
                                state.gestureDetails!.totalScale;
                            double end;

                            //remove old
                            _doubleClickAnimation?.removeListener(
                                _doubleClickAnimationListener);

                            //stop pre
                            _doubleClickAnimationController.stop();

                            //reset to use
                            _doubleClickAnimationController.reset();

                            if (begin == doubleTapScales[0]) {
                              end = doubleTapScales[1];
                            } else {
                              end = doubleTapScales[0];
                            }

                            _doubleClickAnimationListener = () {
                              //outputLogger.i(_animation.value);
                              state.handleDoubleTap(
                                  scale: _doubleClickAnimation!.value,
                                  doubleTapPosition: pointerDownPosition);
                            };
                            _doubleClickAnimation =
                                _doubleClickAnimationController.drive(
                                    Tween<double>(
                                        begin: begin, end: end));

                            _doubleClickAnimation!.addListener(
                                _doubleClickAnimationListener);

                            _doubleClickAnimationController.forward();
                          },
                          mode: ExtendedImageMode.gesture,
                        )),
                  ),
                ),
              ),
              Positioned(
                  left: 10,
                  bottom: 50,
                  child: SizedBox(
                    width: 48,
                    height: 48,
                    child: IconButton(
                      icon: Image.asset(
                        'images/close.png',
                        package: 'tencent_cloud_chat_uikit',
                      ),
                      iconSize: 30,
                      onPressed: close,
                    ),
                  )),
              if (widget.downloadFn != null)
                Positioned(
                  right: 10,
                  bottom: 50,
                  child: SizedBox(
                    width: 48,
                    height: 48,
                    child: IconButton(
                      icon: Image.asset(
                        'images/download.png',
                        package: 'tencent_cloud_chat_uikit',
                      ),
                      iconSize: 30,
                      onPressed: () async {
                        setState(() {
                          isLoading = true;
                        });
                        await widget.downloadFn!();
                        Future.delayed(const Duration(milliseconds: 200),(){
                          setState(() {
                            isLoading = false;
                          });
                        });
                      },
                    ),
                  ),
                ),
              if (isLoading)
                Container(
                  child: LoadingAnimationWidget.staggeredDotsWave(
                    size: 35,
                    color: Colors.white,
                  ),
                  padding: const EdgeInsets.all(30),
                  decoration: const BoxDecoration(
                    color: Color(0xB22b2b2b),
                    borderRadius: BorderRadius.all(Radius.circular(20)),
                  ),
                ),
            ])),
      );
    }));
  }
}
