import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_map_cancellable_tile_provider/flutter_map_cancellable_tile_provider.dart';
import 'package:flutter_map_marker_cluster/flutter_map_marker_cluster.dart';
import 'package:latlong2/latlong.dart';
import 'package:provider/provider.dart';

import '../model/flood_station.dart';
import '../services/flood_station_provider.dart';
import '../widgets/custom_marker.dart';
import '../widgets/map_popup.dart';
import 'flood_station_page.dart';

class MapPage extends StatefulWidget {
  const MapPage({super.key});
  static const routeName = '/map';

  @override
  State<MapPage> createState() => _MapPageState();
}

class _MapPageState extends State<MapPage> {
  final _mapController = MapController();
  late FloodStationProvider _floodStationProvider;
  bool _loading = false;

  @override
  Widget build(BuildContext context) {
    _floodStationProvider = context.watch<FloodStationProvider>();
    if (_loading == true) {
      return Center(
        child: CircularProgressIndicator(),
      );
    } else if (_floodStationProvider.allStations.isEmpty) {
      return Center(
        child: ElevatedButton(
          onPressed: () {
            setState(() {
              _loading = true;
            });
            _floodStationProvider
                .loadAllStations()
                .whenComplete(() => setState(() {
                      _loading = false;
                    }));
          },
          child: Text('Load Map'),
        ),
      );
    }
    return FlutterMap(
      mapController: _mapController,
      options: MapOptions(
        cameraConstraint: CameraConstraint.containCenter(
            bounds: LatLngBounds.fromPoints(_floodStationProvider.allStations
                .map<LatLng>(
                  (e) => LatLng(e.lat, e.long),
                )
                .toList())),
        initialCenter: LatLng(54.81, -4.42),
        initialZoom: 6,
      ),
      children: [
        _openStreetMapTileLayer,
        MarkerClusterLayerWidget(
          options: MarkerClusterLayerOptions(
              maxClusterRadius: 45,
              size: Size(30, 30),
              alignment: Alignment.center,
              padding: EdgeInsets.all(50),
              maxZoom: 15,
              markers: _stationsAsMarkers(_floodStationProvider.allStations),
              builder: _clusterMarkerBuilder),
        )
      ],
    );
  }

  // builds the clustered marker
  Widget _clusterMarkerBuilder(BuildContext context, List<Marker> markers) {
    return Container(
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(20),
        color: Theme.of(context).colorScheme.tertiary,
      ),
      child: Center(
        child: Text(
          markers.length.toString(),
          style: TextStyle(color: Theme.of(context).colorScheme.onTertiary),
        ),
      ),
    );
  }

  // gets a list of markers from the list of all stations
  List<Marker> _stationsAsMarkers(List<FloodStation> stations) {
    return stations
        .map<Marker>(
          (station) => Marker(
            alignment: Alignment.center,
            point: LatLng(station.lat, station.long),
            child: CustomMarker(
              onTap: () => _markerTapped(station),
            ),
          ),
        )
        .toList();
  }

  void _markerTapped(FloodStation station) {
    showDialog(
      context: context,
      builder: (context) => MapPopup(
          station: station,
          onShowTapped: () {
            _floodStationProvider.selectedStation = station;
            Navigator.of(context).pushNamed(FloodStationPage.routeName);
          }),
    );
  }
}

TileLayer get _openStreetMapTileLayer => TileLayer(
      urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
      userAgentPackageName: 'dev.fleaflet.flutter_map.example',
      tileProvider: CancellableNetworkTileProvider(),
    );
