import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_map_location_marker/flutter_map_location_marker.dart';
import 'package:flutter_polyline_points/flutter_polyline_points.dart';
import 'package:geojson_vi/geojson_vi.dart';
import 'package:get/get.dart';
import 'package:latlong2/latlong.dart';
import 'package:gifunavi/pages/permission/permission.dart';
import 'package:gifunavi/pages/settings/settings_binding.dart';
import 'package:gifunavi/model/destination.dart';
import 'package:gifunavi/pages/destination/destination_controller.dart';
import 'package:gifunavi/pages/index/index_controller.dart';
import 'package:gifunavi/utils/database_helper.dart';
import 'package:gifunavi/utils/location_controller.dart';
import 'package:gifunavi/utils/text_util.dart';
import 'package:gifunavi/widgets/base_layer_widget.dart';
import 'package:gifunavi/widgets/bottom_sheet_new.dart';
import 'package:gifunavi/widgets/current_position_widget.dart';
import 'package:gifunavi/widgets/game_state_view.dart';
import 'package:gifunavi/pages/settings/settings_controller.dart';

class MapResetController {
  void Function()? resetIdleTimer;
}

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

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

class _MapWidgetState extends State<MapWidget> with WidgetsBindingObserver {
//class _MapWidgetState extends State<MapWidget> {
  final IndexController indexController = Get.find<IndexController>();
  final DestinationController destinationController =
      Get.find<DestinationController>();
  final LocationController locationController = Get.find<LocationController>();
  final SettingsController settingsController = Get.find<SettingsController>();

  late MapController mapController;
  final Completer<MapController> mapControllerCompleter = Completer<MapController>();

  StreamSubscription? subscription;
  Timer? _timer;
  bool curr_marker_display = false;

  final Map<LatLng, Marker> _markerCache = {};
  List<Marker> _markers = [];

  @override
  void initState() {
    super.initState();

    // 追加
    /*
    WidgetsBinding.instance.addPostFrameCallback((_) {
      PermissionController.checkAndRequestPermissions();
    });
     */

    debugPrint('MapWidget: initState called');
    SettingsBinding().dependencies(); // これを追加
    _startIdleTimer();
    mapController = MapController();
    indexController.mapController = mapController;

    // added by Akira
    WidgetsBinding.instance.addObserver(this);
    _startIdleTimer();

    // マップの操作イベントをリッスンして、_resetTimerを呼び出す
    mapController.mapEventStream.listen((MapEvent mapEvent) {
      if (mapEvent is MapEventMove || mapEvent is MapEventFlingAnimation) {
        _resetTimer();
      }
    });

    // MapControllerの初期化が完了するまで待機
    WidgetsBinding.instance.addPostFrameCallback((_) {
      debugPrint("MapControllerの初期化が完了");
      setState(() {
        indexController.isMapControllerReady.value = true;
      });
      // MapControllerの初期化が完了したら、IndexControllerのonInitを呼び出す
      //indexController.checkPermission();
      //PermissionController.checkAndRequestPermissions();
    });

    late MapResetController mapResetController = MapResetController();
    mapResetController.resetIdleTimer = _resetIdleTimer;
    Get.put(mapResetController);

    // Add this debug subscription
    subscription = locationController.locationMarkerPositionStreamController.stream.listen(
          (LocationMarkerPosition? position) {
        if (position != null) {
          //debugPrint('Location update received: lat=${position.latitude}, lon=${position.longitude}');
        } else {
          debugPrint('Received null location update');
        }
      },
      onError: (error) {
        debugPrint('Error in location stream: $error');
      },
      onDone: () {
        debugPrint('Location stream closed');
      },
    );

//    indexController.mapController = MapController(initCompleter: mapControllerCompleter);

  }

  void _resetIdleTimer() {
    debugPrint("_resetIdleTimer...");
    _timer?.cancel();
    _startIdleTimer();
  }

  @override
  void dispose() {
    debugPrint('MapWidget: dispose called');
    WidgetsBinding.instance.removeObserver(this); // added

    mapController.dispose();
    _timer?.cancel();
    super.dispose();
  }

  // added by Akira
  /*
  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    debugPrint("MapWidget:didChangeAppLifecycleState...state=${state}");

    if (state == AppLifecycleState.resumed) {
      _resetTimer();
    }
  }
   */

  // _centerMapOnUser を10秒間でコール
  Future<void> _startIdleTimer() async {
    //debugPrint("_startIdleTimer ....");
    SettingsController settingsController;

    // SettingsControllerが利用可能になるまで待機
    while (true) {
      try {
        settingsController = Get.find<SettingsController>();
        break; // SettingsControllerが見つかったらループを抜ける
      } catch (e) {
        // SettingsControllerがまだ利用可能でない場合は少し待ってから再試行
        await Future.delayed(const Duration(milliseconds: 100));
      }
    }

    if (!settingsController.autoReturnDisabled.value) {
      _timer = Timer(settingsController.timerDuration.value, _centerMapOnUser);
    }

  }

  // タイマーをリセットして_startIdleTimer をコール
  void _resetTimer() {
    //debugPrint("_resetTimer ....");
    _timer?.cancel();
    _startIdleTimer();
  }

  // マッぷを現在位置を中心にする。
  void _centerMapOnUser() {
    //debugPrint("_centerMapOnUser ....");
    if (mounted) {
      //debugPrint("_centerMapOnUser => centering ....");
      destinationController.centerMapToCurrentLocation();
    }
  }

  Future<void> _initMarkers() async {
    List<Marker> markers = await _getMarkers();
    setState(() {
      _markers = markers;
    });
  }

  Future<List<Marker>> _getMarkers() async {
    debugPrint('Getting markers...');
    if (indexController.isLoadingLocations.value) {
      await Future.doWhile(() async {
        await Future.delayed(const Duration(milliseconds: 100));
        return indexController.isLoadingLocations.value;
      });
    }

    debugPrint('Getting markers...');

      List<Marker> markers = [];
    if (indexController.locations.isNotEmpty && indexController.locations[0].features.isNotEmpty) {
      for (var feature in indexController.locations[0].features) {
        GeoJSONMultiPoint point = feature!.geometry as GeoJSONMultiPoint;
        LatLng latLng = LatLng(point.coordinates[0][1], point.coordinates[0][0]);

        markers.add(Marker(
          point: latLng,
          width: 30.0,
          height: 30.0,
          child: getMarkerShape(feature),
        ));

      }
    }else{
      debugPrint('No locations or features available');

    }
    return markers;
  }


//  Widget getMarkerShape(GeoJSONFeature i, BuildContext context) {
  Widget getMarkerShape(GeoJSONFeature i) {
    GeoJSONMultiPoint p = i.geometry as GeoJSONMultiPoint;
    return InkWell(
      onTap: () {
        GeoJSONFeature? fs = indexController.getFeatureForLatLong(
            p.coordinates[0][1], p.coordinates[0][0]);
        if (fs != null) {
          indexController.currentFeature.clear();
          indexController.currentFeature.add(fs);

          Destination des = destinationController.festuretoDestination(fs);

          DatabaseHelper db = DatabaseHelper.instance;
          db.getDestinationByLatLon(des.lat!, des.lon!).then((value) {
            destinationController.shouldShowBottomSheet = false;
            showModalBottomSheet(
              constraints:
                  BoxConstraints.loose(Size(Get.width, Get.height * 0.85)),
              context: context,
              isScrollControlled: true,
              isDismissible: true,
              builder: ((context) => BottomSheetNew(
                  destination: des, isAlreadyCheckedIn: value.isNotEmpty)),
            ).whenComplete(() {
              destinationController.shouldShowBottomSheet = true;
              destinationController.skipGps = false;
            });
          });
        }
      },
      child: Stack(
        fit: StackFit.expand,
        children: [
          Container(  // マーカー
            height: 32,
            width: 32,
            decoration: BoxDecoration(
              shape: BoxShape.circle,
              color: Colors.transparent,
              border: Border.all(
                color: i.properties!['buy_point'] > 0
                    ? Colors.blue
                    : Colors.red,
                width: 3,
                style: BorderStyle.solid,
              ),
            ),
            child: Stack(
              alignment: Alignment.center,
              children: [
                const Icon(
                  Icons.circle,
                  size: 6.0,
                ),
                i.properties!['cp'] <= 0 ? Transform.translate
                  (
                  offset: const Offset(-3, 0),  //-3
                  child: Transform.rotate(
                      alignment: Alignment.centerLeft,
                      origin: Offset.fromDirection(1, 26),
                      angle: 270 * pi / 180,
                      child: const Icon(
                        Icons.play_arrow_outlined,
                        color: Colors.red,
                        size: 70,
                      )),
                )

                    : Container(
                  color: Colors.transparent,
                ),
              ],
            ),
          ),
          Transform.translate(
            offset: const Offset(30, 0), // 30,0
            child: Align(
              alignment: Alignment.center,
              child: Container (
                //width: 80, // 幅を指定
                //height: 60, // 40
                //color: Colors.purple.withOpacity(0.2),
                color: Colors.transparent,

                //child: Text('          ').
                //constraints: const BoxConstraints(maxWidth: 60.0), // 最大幅を設定
                //constraints: BoxConstraints(maxWidth: maxWidth), // 最大幅を設定
                //color: Colors.purple.withOpacity(0.2),
                child: Stack(
                  children: <Widget>[
                    Text( // アウトライン
                      TextUtils.getDisplayTextFeture(i),
                      style: TextStyle(
                        fontSize: 16, // 16
                        fontWeight: FontWeight.w700,
                        overflow: TextOverflow.visible,
                        //height: 1.2,
                        foreground: Paint()
                          ..style = PaintingStyle.stroke
                          ..strokeWidth = 1 // 2
                          ..color = Colors.white,
                      ),
                      maxLines: 1, // テキストを1行に制限
                      softWrap: false, // テキストの折り返しを無効化
                    ),
                    Text( // テキスト
                      TextUtils.getDisplayTextFeture(i),
                      style: const TextStyle(
                        fontSize: 16,
                        fontWeight: FontWeight.w700,
                        overflow: TextOverflow.visible,
                        //fontWeight: FontWeight.bold,
                        //height: 1.2,
                        color: Colors.black,
                      ),
                      maxLines: 1, // テキストを1行に制限
                      softWrap: false, // テキストの折り返しを無効化
                    ),
                  ],
                ),

              ),
            ),
          )
        ],
      ),
    );
  }

  List<LatLng>? getPoints() {
    List<LatLng> pts = [];
    for (PointLatLng p in indexController.routePoints) {
      LatLng l = LatLng(p.latitude, p.longitude);
      pts.add(l);
    }
    return pts;
  }

  @override
  Widget build(BuildContext context) {
    final settingsController = Get.find<SettingsController>(); // これを追加
    //final PopupController popupController = PopupController();
    return Stack(
      children: [
        Obx(() => indexController.isLoading.value == true
            ? const Padding(
                padding: EdgeInsets.only(top: 60.0),
                child: CircularProgressIndicator(),
              )
            : FlutterMap(
                mapController: mapController,
                //mapController: indexController.mapController,
                options: MapOptions(
                  maxZoom: 18.4,
                  onMapReady: () {
                    _initMarkers();
                    //indexController.isMapControllerReady.value = true;
                  },
                  initialCenter:
                      const LatLng(37.15319600454702, 139.58765950528198),
                  bounds: indexController.currentBound.isNotEmpty
                      ? indexController.currentBound[0]
                      : LatLngBounds.fromPoints([
                          const LatLng(35.03999881162295, 136.40587119778962),
                          const LatLng(36.642756778706904, 137.95226720406063)
                        ]),
                  initialZoom: 1,
                  interactiveFlags:
                      InteractiveFlag.pinchZoom | InteractiveFlag.drag,
                  onPositionChanged: (MapPosition pos, hasGesture) {
                    if (hasGesture) {
                      _resetTimer();
                    }
                    indexController.currentBound = [pos.bounds!];
                  },
                  onMapEvent: (MapEvent mapEvent) {
                    //debugPrint('Map event: ${mapEvent.runtimeType}');
                    if (mapEvent is MapEventMove) {
                      destinationController.shouldShowBottomSheet = true;
                    }
                  },
                  //onTap: (_, __) => popupController.hideAllPopups(),
                ),
                children: [
                  const BaseLayer(),
                  // ルートのポリライン表示
                  Obx(
                    () => indexController.routePointLenght > 0
                        ? PolylineLayer(
                            polylines: [
                              Polyline(
                                points: getPoints()!,
                                strokeWidth: 6.0,
                                color: Colors.indigo,
                              ),
                            ],
                          )
                        : Container(),
                  ),
                  // 現在位置のマーカー
                  CurrentLocationLayer(
                    positionStream: locationController
                        .locationMarkerPositionStreamController.stream,
                    //alignDirectionOnUpdate: AlignOnUpdate.never,
                    style: const LocationMarkerStyle(
                      marker: Stack(
                        children: [
                          CircleAvatar(
                            radius: 13.5,
                            backgroundColor: Colors.blue,
                            child: Icon(Icons.navigation, color: Colors.white),
                          ),
                        ],
                      ),
                      markerSize: Size(27, 27),
                      markerDirection: MarkerDirection.heading,
                    ),
                    //child: const Icon(Icons.navigation),
                  ),

                  FutureBuilder<List<Marker>>(
                    future: indexController.locations.isNotEmpty ? _getMarkers() : null,
                    builder: (context, snapshot) {
                      if (snapshot.connectionState == ConnectionState.waiting) {
                        return const Center(child: CircularProgressIndicator());
                      } else if (snapshot.hasError) {
                        return const Center(child: Text('マーカーの読み込みに失敗しました'));
                      } else {
                        return MarkerLayer(markers: snapshot.data ?? []);
                      }
                    },
                  ),
                  //MarkerLayer(markers: indexController.locations.isNotEmpty ? _getMarkers() : []),
                ],
              )),
        const Positioned(top: 0, left: 0, child: GameStateWidget()),
        const Positioned(bottom: 10, right: 10, child: CurrentPosition()),
        StreamBuilder<LocationMarkerPosition?>(
          stream: locationController.locationMarkerPositionStream,
          builder: (context, snapshot) {
            if (!snapshot.hasData) {
              //debugPrint("====== Not display current marker");
              curr_marker_display = true;
            }else if(curr_marker_display){
              debugPrint("====== Displayed current marker");
              curr_marker_display = false;
            }
            return Container();
          },
        )
      ],
    );
  }
}
