// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:math' as Math;
import 'package:flutter/material.dart';
import 'package:maplibre/maplibre.dart';
import 'package:maplibre_gl/maplibre_gl.dart' as gl;
import '../ecs/system.dart';

abstract class ExamplePage extends StatelessWidget {
  const ExamplePage(
    this.leading,
    this.title, {
    this.needsLocationPermission = true,
    super.key,
  });

  final Widget leading;
  final String title;
  final bool needsLocationPermission;
}


class MapUiPage extends ExamplePage {
  const MapUiPage({super.key}) : super(const Icon(Icons.map), '态势');

  @override
  Widget build(BuildContext context) {
    return const MapUiBody();
  }
}

class MapUiBody extends StatefulWidget {
  const MapUiBody({super.key});

  @override
  State<MapUiBody> createState() => MapUiBodyState();
  
  /// 静态方法，用于通过 GlobalKey 获取 MapUiBodyState 实例
  static MapUiBodyState? of(BuildContext context) {
    final mapUiBody = context.findAncestorWidgetOfExactType<MapUiBody>();
    if (mapUiBody?.key is GlobalKey<MapUiBodyState>) {
      final key = mapUiBody?.key as GlobalKey<MapUiBodyState>;
      return key.currentState;
    }
    return null;
  }
}

class MapUiBodyState extends State<MapUiBody> with TickerProviderStateMixin {
  late final MapController _controller;
  final GlobalKey _mapKey = GlobalKey();
  
  // MapSystem 实例，用于通过系统调用地图接口
  late final MapSystem mapSystem;

  final _markerPositions = [
    const Geographic(lon: -10, lat: 0),
    const Geographic(lon: -5, lat: 0),
    const Geographic(lon: 0, lat: 0),
    const Geographic(lon: 5, lat: 0),
  ];

  // 自定义图片标记数据
  final _customMarkers = <Feature<Point>>[];
  bool _customMarkerImageLoaded = false;

  // 圆形数据
  final _circles = <Feature<Point>>[];

  // 多边形数据（包括扇形和长方形）
  final _polygons = <Feature<Polygon>>[];

  Geographic? _originalPosition;
  MapGestures _mapGestures = const MapGestures.all();

  @override
  void initState() {
    super.initState();
    // 初始化 MapSystem，并将 this 传递给它
    mapSystem = MapSystem(mapUiBodyState: this);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      //appBar: AppBar(title: const Text('Interactive Widget Layer')),
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          const Padding(
            padding: EdgeInsets.only(left: 16, bottom: 8),
            
          ),
          Expanded(
            child: MapLibreMap(
              key: _mapKey,
              options: MapOptions(
                initZoom: 3,
                initCenter: const Geographic(lon: 0, lat: 0),
                initStyle: "assets/osm_style.json",
                gestures: _mapGestures,
              ),
              onMapCreated: (controller) => _controller = controller,
              onEvent: (event) async {
                if (event is MapEventStyleLoaded) {
                  // 加载自定义标记图片
                  await event.style.addImageFromIconData(
                    id: 'custom-marker',
                    iconData: Icons.location_on,
                    color: Colors.blue,
                  );
                  setState(() {
                    _customMarkerImageLoaded = true;
                  });
                } else if (event is MapEventLongClick) {
                  final position = event.point;
                  _markerPositions.add(position);

                  setState(() {});
                }
              },
              layers: [
                // 自定义图片标记层
                MarkerLayer(
                  points: _customMarkers.where((marker) => 
                    marker.properties['type'] != 'fixed_circle'
                  ).toList(), // 过滤掉固定圆形
                  iconImage: _customMarkerImageLoaded ? 'custom-marker' : null,
                  iconSize: 0.15,
                  iconAnchor: IconAnchor.bottom,
                ),
                // 圆形层
                CircleLayer(
                  points: _circles,
                  color: Colors.orange.withValues(alpha: 0.5),
                  radius: 20,
                  strokeColor: Colors.red,
                  strokeWidth: 2,
                ),
                // 多边形层（扇形、长方形和圆形）
                PolygonLayer(
                  polygons: _polygons,
                  color: Colors.lightBlueAccent.withValues(alpha: 0.6),
                  outlineColor: Colors.blue,
                ),
              ],
              children: [
                WidgetLayer(
                  allowInteraction: true,
                  markers: List.generate(
                    _markerPositions.length,
                    (index) => Marker(
                      size: const Size.square(50),
                      point: _markerPositions[index],
                      child: GestureDetector(
                        onTap: () => _onTap(index),
                        onLongPressStart: (details) =>
                            _onLongPress(index, details),
                        onPanStart: (details) => _onLongPanStart(details, index),
                        onPanUpdate: (details) async =>
                            _onPanUpdate(details, index),
                        onPanEnd: (details) async => _onPanEnd(details, index),
                        child: const Icon(
                          Icons.location_on,
                          color: Colors.red,
                          size: 50,
                        ),
                      ),
                      alignment: Alignment.bottomCenter,
                    ),
                  ),
                ),
                // 添加固定圆形的Widget
                WidgetLayer(
                  allowInteraction: false, // 固定圆形不需要交互
                  markers: _customMarkers
                      .where((marker) => marker.properties['type'] == 'fixed_circle')
                      .map((marker) {
                        final pointGeometry = marker.geometry as Point;
                        // 使用Point的position属性获取坐标
                        final geographic = Geographic(
                          lon: pointGeometry.position.x,
                          lat: pointGeometry.position.y,
                        );
                        return Marker(
                          size: Size.fromRadius(marker.properties['radius']?.toDouble() ?? 20.0),
                          point: geographic,
                          child: IgnorePointer(  // 忽略指针事件，确保不会干扰地图手势
                            child: Container(
                              width: (marker.properties['radius']?.toDouble() ?? 20.0) * 2,
                              height: (marker.properties['radius']?.toDouble() ?? 20.0) * 2,
                              decoration: BoxDecoration(
                                color: marker.properties['color'] ?? Colors.orange,
                                shape: BoxShape.circle,
                                border: Border.all(
                                  color: marker.properties['strokeColor'] ?? Colors.red,
                                  width: marker.properties['strokeWidth']?.toDouble() ?? 2.0,
                                ),
                              ),
                            ),
                          ),
                          alignment: Alignment.center,
                        );
                      })
                      .toList(),
                ),
                // display the UI widgets above the widget markers.
                const MapScalebar(),
                const SourceAttribution(),
                const MapControlButtons(),
                const MapCompass(),
              ],
            ),
          ),
        ],
      ),
    );
  }

  Future<Geographic> _toLngLat(Offset eventOffset) async {
    final mapRenderBox =
        _mapKey.currentContext?.findRenderObject() as RenderBox?;

    assert(mapRenderBox != null, 'RenderBox of Map should never be null');

    final mapOffset = mapRenderBox!.localToGlobal(Offset.zero);

    final offset = Offset(
      eventOffset.dx - mapOffset.dx,
      eventOffset.dy - mapOffset.dy,
    );

    return _controller.toLngLat(offset);
  }

  void _onLongPress(int index, LongPressStartDetails details) {
    final offset = details.globalPosition;

    showMenu(
      context: context,
      position: RelativeRect.fromLTRB(
        offset.dx,
        offset.dy,
        MediaQuery.of(context).size.width - offset.dx,
        MediaQuery.of(context).size.height - offset.dy,
      ),
      items: [
        const PopupMenuItem<void>(child: Text('Edit')),
        PopupMenuItem<void>(
          onTap: () async {
            final isConfirmed = await _showConfirmationDialogDelete(index);

            if (isConfirmed) {
              _markerPositions.removeAt(index);

              setState(() {});
            }
          },
          child: const Text('Delete'),
        ),
      ],
    );
  }

  Future<void> _onPanEnd(DragEndDetails details, int index) async {
    final isAccepted = await _showConfirmationDialogMove();

    if (!isAccepted) {
      _markerPositions[index] = _originalPosition!;
    } else {
      final newPosition = await _toLngLat(details.globalPosition);
      _markerPositions[index] = newPosition;
    }

    _originalPosition = null;

    setState(() {
      _mapGestures = const MapGestures.all();
    });
  }

  void _onLongPanStart(DragStartDetails details, int index) {
    // Keep original position in case of discarded move
    _originalPosition = Geographic.from(_markerPositions[index]);

    setState(() {
      // Disable camera panning while a marker gets moved.
      _mapGestures = const MapGestures.all(pan: false);
    });
  }

  Future<void> _onPanUpdate(DragUpdateDetails details, int index) async {
    final newPosition = await _toLngLat(details.globalPosition);
    _markerPositions[index] = newPosition;

    setState(() {});
  }

  void _onTap(int index) {
    _showMarkerDetails(index);
  }

  Future<bool> _showConfirmationDialogDelete(int index) async {
    final isConfirmed = await showDialog<bool>(
      context: context,
      builder: (context) => AlertDialog(
        title: Text('Delete marker [$index]?'),
        actions: <Widget>[
          TextButton(
            style: TextButton.styleFrom(
              textStyle: Theme.of(context).textTheme.labelLarge,
            ),
            child: const Text('Cancel'),
            onPressed: () {
              Navigator.of(context).pop(false);
            },
          ),
          TextButton(
            style: TextButton.styleFrom(
              textStyle: Theme.of(context).textTheme.labelLarge,
            ),
            child: const Text('Delete'),
            onPressed: () {
              Navigator.of(context).pop(true);
            },
          ),
        ],
      ),
    );

    return isConfirmed ?? false;
  }

  Future<bool> _showConfirmationDialogMove() async {
    final isConfirmed = await showDialog<bool>(
      context: context,
      builder: (context) => AlertDialog(
        title: const Text('Accept new position?'),
        actions: <Widget>[
          TextButton(
            style: TextButton.styleFrom(
              textStyle: Theme.of(context).textTheme.labelLarge,
            ),
            child: const Text('Discard'),
            onPressed: () {
              Navigator.of(context).pop(false);
            },
          ),
          TextButton(
            style: TextButton.styleFrom(
              textStyle: Theme.of(context).textTheme.labelLarge,
            ),
            child: const Text('Accept'),
            onPressed: () {
              Navigator.of(context).pop(true);
            },
          ),
        ],
      ),
    );

    return isConfirmed ?? false;
  }

  Future<void> _showMarkerDetails(int index) async {
    await showDialog<void>(
      context: context,
      builder: (context) => AlertDialog(
        title: Text('Details marker with index: $index'),
        content: Text('Show here the details of Marker with index $index'),
        actions: <Widget>[
          TextButton(
            style: TextButton.styleFrom(
              textStyle: Theme.of(context).textTheme.labelLarge,
            ),
            child: const Text('Cancel'),
            onPressed: () {
              Navigator.of(context).pop();
            },
          ),
        ],
      ),
    );

    return;
  }

  // ==================== 公共接口方法 ====================

  /// 添加自定义图片标记
  ///
  /// [position] 标记的地理位置
  /// [properties] 可选的属性数据
  void addCustomMarker(Geographic position, {Map<String, dynamic>? properties}) {
    setState(() {
      _customMarkers.add(Feature(
        geometry: Point(position),
        properties: properties,
      ));
    });
  }

  /// 添加圆形
  ///
  /// [position] 圆心的地理位置
  /// [radius] 圆的半径（单位：像素）
  /// [color] 填充颜色
  /// [strokeColor] 边框颜色
  /// [strokeWidth] 边框宽度
  void addCircle(
    Geographic position, {
    double radius = 20,
    Color color = Colors.orange,
    Color strokeColor = Colors.red,
    double strokeWidth = 2,
  }) {
    setState(() {
      _circles.add(Feature(
        geometry: Point(position),
        properties: {
          'radius': radius,
          'color': color,
          'strokeColor': strokeColor,
          'strokeWidth': strokeWidth,
        },
      ));
    });
  }

  /// 添加固定大小的圆形（不随地图缩放）
  ///
  /// [center] 圆心的地理位置
  /// [radius] 圆的半径（单位：米）
  /// [color] 填充颜色
  /// [outlineColor] 边框颜色
  void addFixedCircle(
    Geographic center, {
    required double radius,
    Color color = Colors.orange,
    Color outlineColor = Colors.blue,
  }) {
    // 将半径从米转换为经纬度（度）
    final radiusInDegrees = _metersToDegrees(center, radius);
    
    final points = <Geographic>[];
    
    // 计算圆周上的点（360度）
    for (int i = 0; i <= 36; i++) { // 使用36个点来构成圆形
      final angle = (360 * i / 36) * 3.14159265359 / 180; // 角度转弧度
      
      // 将角度转换为经纬度偏移
      final latOffset = radiusInDegrees * Math.sin(angle);
      final lonOffset = radiusInDegrees * Math.cos(angle);
      
      points.add(Geographic(
        lon: center.lon + lonOffset,
        lat: center.lat + latOffset,
      ));
    }
    
    setState(() {
      _polygons.add(Feature(
        geometry: Polygon.from([points]),
        properties: {
          'color': color,
          'outlineColor': outlineColor,
          'type': 'fixed_circle_geo', // 标记为地理圆形
        },
      ));
    });
  }

  /// 添加扇形
  ///
  /// [center] 扇形中心的地理位置
  /// [radius] 扇形的半径（单位：米）
  /// [startAngle] 起始角度（单位：度，0度表示正东方向）
  /// [endAngle] 结束角度（单位：度）
  /// [segments] 扇形的分段数，值越大越平滑
  /// [color] 填充颜色
  /// [outlineColor] 边框颜色
  void addSector(
    Geographic center, {
    required double radius,
    required double startAngle,
    required double endAngle,
    int segments = 36,
    Color color = Colors.lightBlueAccent,
    Color outlineColor = Colors.blue,
  }) {
    // 将半径从米转换为经纬度（度）
    final radiusInDegrees = _metersToDegrees(center, radius);
    
    final points = <Geographic>[];
    
    // 添加中心点
    points.add(center);
    
    // 计算扇形的弧线上的点
    for (int i = 0; i <= segments; i++) {
      final angle = startAngle + (endAngle - startAngle) * i / segments;
      final angleRad = angle * 3.14159265359 / 180;
      
      // 将角度转换为经纬度偏移
      final latOffset = radiusInDegrees * Math.sin(angleRad);
      final lonOffset = radiusInDegrees * Math.cos(angleRad);
      
      points.add(Geographic(
        lon: center.lon + lonOffset,
        lat: center.lat + latOffset,
      ));
    }
    
    setState(() {
      _polygons.add(Feature(
        geometry: Polygon.from([points]),
        properties: {
          'color': color,
          'outlineColor': outlineColor,
        },
      ));
    });
  }

  /// 添加长方形
  ///
  /// [center] 长方形中心的地理位置
  /// [width] 长方形的宽度（单位：米）
  /// [height] 长方形的高度（单位：米）
  /// [color] 填充颜色
  /// [outlineColor] 边框颜色
  void addRectangle(
    Geographic center, {
    required double width,
    required double height,
    Color color = Colors.lightBlueAccent,
    Color outlineColor = Colors.blue,
  }) {
    // 将宽高从米转换为经纬度（度）
    final widthInDegrees = _metersToDegrees(center, width / 2);
    final heightInDegrees = _metersToDegrees(center, height / 2);
    
    final points = [
      Geographic(lon: center.lon - widthInDegrees, lat: center.lat - heightInDegrees),
      Geographic(lon: center.lon + widthInDegrees, lat: center.lat - heightInDegrees),
      Geographic(lon: center.lon + widthInDegrees, lat: center.lat + heightInDegrees),
      Geographic(lon: center.lon - widthInDegrees, lat: center.lat + heightInDegrees),
      Geographic(lon: center.lon - widthInDegrees, lat: center.lat - heightInDegrees), // 闭合多边形
    ];
    
    setState(() {
      _polygons.add(Feature(
        geometry: Polygon.from([points]),
        properties: {
          'color': color,
          'outlineColor': outlineColor,
        },
      ));
    });
  }

  /// 将距离（米）转换为经纬度（度）
  /// 此方法使用近似计算，适用于小范围区域
  double _metersToDegrees(Geographic center, double meters) {
    // 地球半径，约为6378137米
    const earthRadius = 6378137.0;
    
    // 将米转换为度
    // 1度大约等于111320米（在赤道附近）
    // 但需要考虑纬度的影响，因为经度的距离会随纬度变化
    final latCircumference = 2 * Math.pi * earthRadius; // 纬线周长
    final latFactor = meters / latCircumference * 360; // 纬度方向转换因子
    
    // 经度方向需要考虑纬度的影响
    final lonCircumference = 2 * Math.pi * earthRadius * Math.cos(center.lat * Math.pi / 180); // 经线周长
    final lonFactor = meters / lonCircumference * 360; // 经度方向转换因子
    
    // 返回平均值，对于小范围区域，这个近似是足够的
    return (latFactor + lonFactor) / 2;
  }

  /// 清除所有自定义标记
  void clearCustomMarkers() {
    setState(() {
      _customMarkers.clear();
    });
  }

  /// 清除所有圆形
  void clearCircles() {
    setState(() {
      _circles.clear();
    });
  }

  /// 清除所有多边形（包括扇形和长方形）
  void clearPolygons() {
    setState(() {
      _polygons.clear();
    });
  }

  /// 清除所有自定义图层
  void clearAllCustomLayers() {
    setState(() {
      _customMarkers.clear();
      _circles.clear();
      _polygons.clear();
    });
  }
}

