import 'package:draggable_float_widget/draggable_float_widget.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hbb/common.dart';

import '../../models/model.dart';
import '../pages/chat_page.dart';

OverlayEntry? chatIconOverlayEntry;
OverlayEntry? chatWindowOverlayEntry;

OverlayEntry? mobileActionsOverlayEntry;

class DraggableChatWindow extends StatelessWidget {
  DraggableChatWindow(
      {this.position = Offset.zero, required this.width, required this.height});

  final Offset position;
  final double width;
  final double height;

  @override
  Widget build(BuildContext context) {
    return Draggable(
        checkKeyboard: true,
        position: position,
        width: width,
        height: height,
        builder: (_, onPanUpdate) {
          return isIOS
              ? chatPage
              : Scaffold(
                  resizeToAvoidBottomInset: false,
                  appBar: CustomAppBar(
                    onPanUpdate: onPanUpdate,
                    appBar: Container(
                      color: MyTheme.accent50,
                      height: 50,
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        children: [
                          Padding(
                              padding: EdgeInsets.symmetric(horizontal: 15),
                              child: Text(
                                translate("Chat"),
                                style: TextStyle(
                                    color: Colors.white,
                                    fontFamily: 'WorkSans',
                                    fontWeight: FontWeight.bold,
                                    fontSize: 20),
                              )),
                          Row(
                            crossAxisAlignment: CrossAxisAlignment.center,
                            children: [
                              IconButton(
                                  onPressed: () {
                                    hideChatWindowOverlay();
                                  },
                                  icon: Icon(Icons.keyboard_arrow_down)),
                              IconButton(
                                  onPressed: () {
                                    hideChatWindowOverlay();
                                    hideChatIconOverlay();
                                  },
                                  icon: Icon(Icons.close))
                            ],
                          )
                        ],
                      ),
                    ),
                  ),
                  body: chatPage,
                );
        });
  }
}

class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
  final GestureDragUpdateCallback onPanUpdate;
  final Widget appBar;

  const CustomAppBar(
      {Key? key, required this.onPanUpdate, required this.appBar})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return GestureDetector(onPanUpdate: onPanUpdate, child: appBar);
  }

  @override
  Size get preferredSize => new Size.fromHeight(kToolbarHeight);
}

showChatIconOverlay({Offset offset = const Offset(200, 50)}) {
  if (chatIconOverlayEntry != null) {
    chatIconOverlayEntry!.remove();
  }
  if (globalKey.currentState == null || globalKey.currentState!.overlay == null)
    return;
  final bar = navigationBarKey.currentWidget;
  if (bar != null) {
    if ((bar as BottomNavigationBar).currentIndex == 1) {
      return;
    }
  }
  final globalOverlayState = globalKey.currentState!.overlay!;

  final overlay = OverlayEntry(builder: (context) {
    return DraggableFloatWidget(
        config: DraggableFloatWidgetBaseConfig(
          initPositionYInTop: false,
          initPositionYMarginBorder: 100,
          borderTopContainTopBar: true,
        ),
        child: FloatingActionButton(
            onPressed: () {
              if (chatWindowOverlayEntry == null) {
                showChatWindowOverlay();
              } else {
                hideChatWindowOverlay();
              }
            },
            child: Icon(Icons.message)));
  });
  globalOverlayState.insert(overlay);
  chatIconOverlayEntry = overlay;
}

hideChatIconOverlay() {
  if (chatIconOverlayEntry != null) {
    chatIconOverlayEntry!.remove();
    chatIconOverlayEntry = null;
  }
}

showChatWindowOverlay() {
  if (chatWindowOverlayEntry != null) return;
  if (globalKey.currentState == null || globalKey.currentState!.overlay == null)
    return;
  final globalOverlayState = globalKey.currentState!.overlay!;

  final overlay = OverlayEntry(builder: (context) {
    return DraggableChatWindow(
        position: Offset(20, 80), width: 250, height: 350);
  });
  globalOverlayState.insert(overlay);
  chatWindowOverlayEntry = overlay;
}

hideChatWindowOverlay() {
  if (chatWindowOverlayEntry != null) {
    chatWindowOverlayEntry!.remove();
    chatWindowOverlayEntry = null;
    return;
  }
}

toggleChatOverlay() {
  if (chatIconOverlayEntry == null || chatWindowOverlayEntry == null) {
    FFI.invokeMethod("enable_soft_keyboard", true);
    showChatIconOverlay();
    showChatWindowOverlay();
  } else {
    hideChatIconOverlay();
    hideChatWindowOverlay();
  }
}

/// floating buttons of back/home/recent actions for android
class DraggableMobileActions extends StatelessWidget {
  DraggableMobileActions(
      {this.position = Offset.zero,
      this.onBackPressed,
      this.onRecentPressed,
      this.onHomePressed,
      required this.width,
      required this.height});

  final Offset position;
  final double width;
  final double height;
  final VoidCallback? onBackPressed;
  final VoidCallback? onHomePressed;
  final VoidCallback? onRecentPressed;

  @override
  Widget build(BuildContext context) {
    return Draggable(
        position: position,
        width: width,
        height: height,
        builder: (_, onPanUpdate) {
          return GestureDetector(
              onPanUpdate: onPanUpdate,
              child: Container(
                decoration: BoxDecoration(
                    color: MyTheme.accent.withOpacity(0.4),
                    borderRadius: BorderRadius.all(Radius.circular(15))),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  children: [
                    IconButton(
                        color: MyTheme.white,
                        onPressed: onBackPressed,
                        icon: Icon(Icons.arrow_back)),
                    IconButton(
                        color: MyTheme.white,
                        onPressed: onHomePressed,
                        icon: Icon(Icons.home)),
                    IconButton(
                        color: MyTheme.white,
                        onPressed: onRecentPressed,
                        icon: Icon(Icons.more_horiz)),
                    VerticalDivider(
                      width: 0,
                      thickness: 2,
                      indent: 10,
                      endIndent: 10,
                    ),
                    IconButton(
                        color: MyTheme.white,
                        onPressed: hideMobileActionsOverlay,
                        icon: Icon(Icons.keyboard_arrow_down)),
                  ],
                ),
              ));
        });
  }
}

showMobileActionsOverlay() {
  if (mobileActionsOverlayEntry != null) return;
  if (globalKey.currentContext == null ||
      globalKey.currentState == null ||
      globalKey.currentState!.overlay == null) return;
  final globalOverlayState = globalKey.currentState!.overlay!;

  // compute overlay position
  final screenW = MediaQuery.of(globalKey.currentContext!).size.width;
  final screenH = MediaQuery.of(globalKey.currentContext!).size.height;
  final double overlayW = 200;
  final double overlayH = 45;
  final left = (screenW - overlayW) / 2;
  final top = screenH - overlayH - 80;

  final overlay = OverlayEntry(builder: (context) {
    return DraggableMobileActions(
      position: Offset(left, top),
      width: overlayW,
      height: overlayH,
      onBackPressed: () => FFI.tap(MouseButtons.right),
      onHomePressed: () => FFI.tap(MouseButtons.wheel),
      onRecentPressed: () async {
        FFI.sendMouse('down', MouseButtons.wheel);
        await Future.delayed(Duration(milliseconds: 500));
        FFI.sendMouse('up', MouseButtons.wheel);
      },
    );
  });
  globalOverlayState.insert(overlay);
  mobileActionsOverlayEntry = overlay;
}

hideMobileActionsOverlay() {
  if (mobileActionsOverlayEntry != null) {
    mobileActionsOverlayEntry!.remove();
    mobileActionsOverlayEntry = null;
    return;
  }
}

class Draggable extends StatefulWidget {
  Draggable(
      {this.checkKeyboard = false,
      this.checkScreenSize = false,
      this.position = Offset.zero,
      required this.width,
      required this.height,
      required this.builder});

  final bool checkKeyboard;
  final bool checkScreenSize;
  final Offset position;
  final double width;
  final double height;
  final Widget Function(BuildContext, GestureDragUpdateCallback) builder;

  @override
  State<StatefulWidget> createState() => _DraggableState();
}

class _DraggableState extends State<Draggable> {
  late Offset _position;
  bool _keyboardVisible = false;
  double _saveHeight = 0;
  double _lastBottomHeight = 0;

  @override
  void initState() {
    super.initState();
    _position = widget.position;
  }

  void onPanUpdate(DragUpdateDetails d) {
    final offset = d.delta;
    final size = MediaQuery.of(context).size;
    double x = 0;
    double y = 0;

    if (_position.dx + offset.dx + widget.width > size.width) {
      x = size.width - widget.width;
    } else if (_position.dx + offset.dx < 0) {
      x = 0;
    } else {
      x = _position.dx + offset.dx;
    }

    if (_position.dy + offset.dy + widget.height > size.height) {
      y = size.height - widget.height;
    } else if (_position.dy + offset.dy < 0) {
      y = 0;
    } else {
      y = _position.dy + offset.dy;
    }
    setState(() {
      _position = Offset(x, y);
    });
  }

  checkScreenSize() {}

  checkKeyboard() {
    final bottomHeight = MediaQuery.of(context).viewInsets.bottom;
    final currentVisible = bottomHeight != 0;

    debugPrint(bottomHeight.toString() + currentVisible.toString());
    // save
    if (!_keyboardVisible && currentVisible) {
      _saveHeight = _position.dy;
    }

    // reset
    if (_lastBottomHeight > 0 && bottomHeight == 0) {
      setState(() {
        _position = Offset(_position.dx, _saveHeight);
      });
    }

    // onKeyboardVisible
    if (_keyboardVisible && currentVisible) {
      final sumHeight = bottomHeight + widget.height;
      final contextHeight = MediaQuery.of(context).size.height;
      if (sumHeight + _position.dy > contextHeight) {
        final y = contextHeight - sumHeight;
        setState(() {
          _position = Offset(_position.dx, y);
        });
      }
    }

    _keyboardVisible = currentVisible;
    _lastBottomHeight = bottomHeight;
  }

  @override
  Widget build(BuildContext context) {
    if (widget.checkKeyboard) {
      checkKeyboard();
    }
    if (widget.checkKeyboard) {
      checkScreenSize();
    }
    return Positioned(
        top: _position.dy,
        left: _position.dx,
        width: widget.width,
        height: widget.height,
        child: widget.builder(context, onPanUpdate));
  }
}