import 'dart:convert';

import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter_map/src/consts/map_constants.dart';
import 'package:flutter_map/src/consts/marker_type.dart';
import 'package:flutter_map/src/core/map_controller.dart';
import 'package:flutter_map/src/entity/marker.dart';

import '../../flutter_map.dart';
import '../entity/polyline.dart';

class MapWidget extends StatefulWidget {
  final MapController? controller;
  final MarkerTapCallback? onMarkerTap;
  final List<Marker>? markers;
  final List<Polyline>? polyline;
  final MapPadding? mapPadding;
  final bool isAnimateCamera;
  final bool? isShowLogo;
  final bool? interactionIsEnabled;

  const MapWidget({
    super.key,
    this.controller,
    this.onMarkerTap,
    this.mapPadding,
    this.markers,
    this.isAnimateCamera = true,
    this.isShowLogo,
    this.interactionIsEnabled,
    this.polyline,
  });

  @override
  State<MapWidget> createState() => _MapWidgetState();
}

class _MapWidgetState extends State<MapWidget> {
  final String mapViewType = MapConstants.mapWidgetViewType;

  final List<LatLng> cameraPoints = [];

  @override
  void didUpdateWidget(covariant MapWidget oldWidget) {
    super.didUpdateWidget(oldWidget);
    cameraPoints.clear();
    if (oldWidget.markers != widget.markers) {
      if (widget.markers == null || widget.markers!.isEmpty) {
        widget.controller?.clearAllMarkers();
      } else {
        showMarker();
      }
    }
    if (oldWidget.polyline != widget.polyline) {
      widget.controller?.clearAllPolylines();
      showPolyline();
    }
    animateCamera();
  }

  void showMarker() {
    if (widget.markers == null || widget.markers!.isEmpty) {
      return;
    }
    final markerPoints = widget.markers
        ?.map((marker) =>
            LatLng(latitude: marker.latitude, longitude: marker.longitude))
        .toList();
    cameraPoints.addAll(markerPoints ?? []);
    widget.controller?.replaceAllMarkers(widget.markers ?? []);
  }

  void showPolyline() {
    if (widget.polyline == null || widget.polyline!.isEmpty) {
      return;
    }
    for (var line in widget.polyline!) {
      if (line.points.isNotEmpty) {
        cameraPoints.add(line.points.first);
        widget.controller?.addPolyline(line, isAnimateCamera: false);
      }
    }
  }

  void animateCamera() {
    if (cameraPoints.isNotEmpty) {
      widget.controller
          ?.moveToSuitableLocation(cameraPoints, mapPadding: widget.mapPadding);
    }
  }

  @override
  void initState() {
    super.initState();
    if (widget.isShowLogo != null) {
      widget.controller?.setMapLogoVisible(widget.isShowLogo!);
    }
    if (widget.interactionIsEnabled != null) {
      widget.controller?.setMapInteractionEnabled(widget.interactionIsEnabled!);
    }

    showMarker();
    showPolyline();
    animateCamera();
  }

  @override
  Widget build(BuildContext context) {
    debugPrint(
        'MapWidget...build...mapViewType==>$mapViewType,defaultTargetPlatform==>$defaultTargetPlatform');
    if (defaultTargetPlatform == TargetPlatform.android) {
      return PlatformViewLink(
          surfaceFactory: (context, controller) {
            return AndroidViewSurface(
              controller: controller as AndroidViewController,
              gestureRecognizers: const <Factory<
                  OneSequenceGestureRecognizer>>{},
              hitTestBehavior: PlatformViewHitTestBehavior.opaque,
            );
          },
          onCreatePlatformView: onCreatePlatformView,
          viewType: mapViewType);
    } else if (defaultTargetPlatform == TargetPlatform.iOS) {
      return UiKitView(
        viewType: mapViewType,
        onPlatformViewCreated: onPlatformViewCreated,
        creationParamsCodec: const StandardMessageCodec(),
      );
    }
    return Text('当前平台:$defaultTargetPlatform, 不支持使用地图插件');
  }

  PlatformViewController onCreatePlatformView(
      PlatformViewCreationParams params) {
    return PlatformViewsService.initSurfaceAndroidView(
      id: params.id,
      viewType: mapViewType,
      layoutDirection: TextDirection.ltr,
      creationParams: <String, dynamic>{},
      creationParamsCodec: const StandardMessageCodec(),
    )
      ..addOnPlatformViewCreatedListener(params.onPlatformViewCreated)
      ..addOnPlatformViewCreatedListener(onPlatformViewCreated)
      ..create();
  }

  Future<void> onPlatformViewCreated(int viewId) async {
    MethodChannel mapChannel =
        MethodChannel('${MapConstants.mapViewChannelName}$viewId');
    widget.controller?.setChannel(mapChannel);
    mapChannel.setMethodCallHandler(_mapMethodCallHandler);
  }

  Future<dynamic> _mapMethodCallHandler(MethodCall call) async {
    debugPrint(
        '_mapMethodCallHandler...call.method==>${call.method},call.arguments==>${call.arguments}');
    switch (call.method) {
      case MapConstants.methodMarkerOnTap:
        Map<String, dynamic> jsonMap = jsonDecode(call.arguments);
        Marker marker = Marker.fromJson(jsonMap);
        widget.onMarkerTap?.call(marker);
        break;
    }
  }
}
