import 'dart:math';

import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart';
import 'package:latlong2/latlong.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:oc_front/core/services/specialized_services/datacenter_service.dart';
import 'package:oc_front/main.dart';
import 'package:oc_front/models/resources/compute.dart';
import 'package:oc_front/models/resources/resources.dart';
import 'package:oc_front/models/resources/storage.dart';
import 'package:oc_front/pages/abstract_page.dart';
import 'package:oc_front/widgets/items/item_row.dart';


class  MapFactory implements AbstractFactory {
  @override GlobalKey getKey() { return key; }
  @override String? getSearch() { return ""; }
  @override void back(BuildContext context) { }
  static GlobalKey<MapPageWidgetState> key = GlobalKey<MapPageWidgetState>();
  @override bool searchFill() { return false; }
  @override Widget factory(GoRouterState state, List<String> args) { return MapPageWidget(); }
  @override void search(BuildContext context, bool special) { }
}
double menuSize = 0;
class MapPageWidget extends StatefulWidget {
  bool isShowed = false;
  final DatacenterService _service = DatacenterService();
  MapPageWidget(): super(key: MapFactory.key);
  @override MapPageWidgetState createState() => MapPageWidgetState();
  static void search(BuildContext context) { }
  static Widget factory() { return MapPageWidget(); }
}
class MapPageWidgetState extends State<MapPageWidget> {
  double currentZoom = 2.0;
  LatLng currentCenter = const LatLng(51.5, -0.09);
  static final MapController _mapController = MapController();
  bool selected = true;

  @override Widget build(BuildContext context) {
    return FutureBuilder(future: widget._service.all(context), builder: (BuildContext context, AsyncSnapshot snapshot) {
        Map<String, Map<AbstractItem, LatLng>> coordinates = {};
        List<Marker> markerCoordinates = [];
        if (snapshot.data != null&& snapshot.data!.data != null) {
          for (var element in snapshot.data!.data!.values) {
            if (element["type"] == "storage") { 
              StorageItem resource = StorageItem().deserialize(element);
              var instance = resource.getSelectedInstance();
              if (instance == null || instance.location == null) { continue; }
              if (coordinates[resource.topic] == null) { coordinates[resource.topic] = {}; }
              coordinates[resource.topic]![resource] = LatLng(instance.location!.latitude ?? 0, instance.location!.longitude ?? 0);
            } else if (element["type"] == "compute") {
              ComputeItem resource = ComputeItem().deserialize(element);
              var instance = resource.getSelectedInstance();
              if (instance == null || instance.location == null) { continue; }
              if (coordinates[resource.topic] == null) { coordinates[resource.topic] = {}; }
              var lr = Random().nextInt(max(1, 100)) / 10000;
              var lfr = Random().nextInt(max(1, 100)) / 10000;
              coordinates[resource.topic]![resource] = LatLng((instance.location!.latitude ?? 0) + lr, (instance.location!.longitude ?? 0) + lfr);
            }
          }
          for (var topic in coordinates.keys) {
            for (var coord in coordinates[topic]!.keys) {
              markerCoordinates.add(Marker(
                width: 25,
                height: 30,
                point: coordinates[topic]![coord]!,
                child: HoverMenu( width: 110, title: Container(  alignment: Alignment.center,
                    constraints: const BoxConstraints( maxHeight: 100, maxWidth: 100 ), 
                    child: Icon(FontAwesomeIcons.locationDot, 
                      shadows: const <Shadow>[Shadow(color: Color.fromRGBO(0, 0, 0, 1), blurRadius: 10.0)],
                      color: getColor(topic)) ),
                    items: [ Container(color: Colors.white, 
                      child: ItemRowWidget(low: true, contextWidth: 290, item: coord))  ]
                  ),
              ));
            }
          }
          Rect rect = Rect.fromCenter( center: MediaQuery.of(context).size.center(Offset.zero),
            width: selected ? menuSize : 0, height: (getMainHeight(context) - 50) > 0 ? (getMainHeight(context) - 50) : 0);
          return Expanded( 
            child : FlutterMap(
                mapController: _mapController,
                options: MapOptions(
                          initialCenter: currentCenter,
                          initialZoom: currentZoom,
                        ),
                children: [
                    TileLayer(
                      urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
                      userAgentPackageName: 'dev.fleaflet.flutter_map.example',
                    ),
                    MarkerLayer(
                      markers: markerCoordinates,
                    ),
                ],
              ),
          );
        } else {
          return const CircularProgressIndicator();
        }
      }
    );
  }
}

class HoverMenuController {
  HoverMenuState? currentState;

  void hideSubMenu() {
    currentState?.hideSubMenu();
  }
}

class HoverMenu extends StatefulWidget {
  final Widget title;
  final double? width;
  final List<Widget> items;
  final HoverMenuController? controller;
  bool isHovered = false;


  HoverMenu({
    Key? key,
    required this.title,
    this.items = const [],
    this.width,
    this.controller,
  }) : super(key: key);

  @override
  HoverMenuState createState() => HoverMenuState();
}

class HoverMenuState extends State<HoverMenu> {
  OverlayEntry? _overlayEntry;
  final _focusNode = FocusNode();

  @override
  void initState() {
    super.initState();
    _focusNode.addListener(_onFocusChanged);

    if (widget.controller != null) {
      widget.controller?.currentState = this;
    }
  }

  @override
  void dispose() {
    _focusNode.dispose();
    super.dispose();
  }

  void _onFocusChanged() {
    if (_focusNode.hasFocus) {
      _overlayEntry = _createOverlayEntry();
      Overlay.of(context).insert(_overlayEntry!);
    } else {
      _overlayEntry?.remove();
      _removeOverlay();
    }
  }

  void _removeOverlay() {
    widget.isHovered = false;
  }

  void hideSubMenu() {
    _focusNode.unfocus();
  }

  @override
  Widget build(BuildContext context) {
    return TextButton(
      style: TextButton.styleFrom(
                  elevation: 0.0,
                  shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0)),
                  splashFactory: NoSplash.splashFactory,
                  padding: EdgeInsets.zero,
                  foregroundColor: Colors.transparent,
                  surfaceTintColor: Colors.transparent,
                  backgroundColor: Colors.transparent,
                  shadowColor: Colors.transparent,
                ),
      focusNode: _focusNode,
      onHover: (isHovered) {
        if (isHovered && !widget.isHovered) {
          _focusNode.requestFocus();
          isHovered = true;
        } else {
          _focusNode.unfocus();
          widget.isHovered = false;
        }
      },
      onPressed: () {},
      child: widget.title,
    );
  }

  OverlayEntry _createOverlayEntry() {
    final renderBox = context.findRenderObject() as RenderBox;
    final size = renderBox.size;
    final offset = renderBox.localToGlobal(Offset.zero);

    return OverlayEntry(
      maintainState: true,
      builder: (context) => Positioned(
        left: offset.dx - 300,
        top: offset.dy + size.height,
        width: 300,
        child: TextButton(
            style: TextButton.styleFrom( 
              padding: EdgeInsets.zero,
              shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0)),
              splashFactory: NoSplash.splashFactory,
              backgroundColor: Colors.transparent,
            ),
            onPressed: () {},
            child: ListView(
                padding: EdgeInsets.zero,
                shrinkWrap: true,
                children: widget.items)),
      ),
    );
  }
}