import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart'; // Import LatLng class from the latlong package
import 'dart:async';
import 'dart:io';
import 'dart:convert';


const String port = "8443";
const String serverURI = "https://127.0.0.1:$port/";
const String mapEndpoint = "update_map";
// NB: if http connection fails, run: adb reverse tcp:8443 tcp:8443
const int fetchInterval = 5;

// main is the entry point for the application, and starts the App() function
void main() {
  runApp(const App());
}

class App extends StatelessWidget {
  const App({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: DefaultPage(),
    );
  }
}

class DefaultPage extends StatefulWidget {
  const DefaultPage({Key? key}) : super(key: key);

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

// MarkerData holds data for the dynamicllay allocated markers
class MarkerData {
  final LatLng location;
  final double size;
  final Color color;

  MarkerData({required this.location, required this.size, required this.color});
}

// parseMarkerData parses jsonData into an object of type MakerData
List<MarkerData> parseMarkerData(String jsonString) {
  final parsed = json.decode(jsonString);
  return List<MarkerData>.from(parsed.map((data) => MarkerData(
    location: LatLng(data['latitude'], data['longitude']),
    size: data['size'].toDouble(),
    color: parseColor(data['color']),
  )));
}

// parseColor parses the color strings into Colors types
Color parseColor(String colorString) {
  switch (colorString) {
    case 'blue':
      return Colors.blue;
    case 'red':
      return Colors.red;
    case 'green':
      return Colors.green;
    default:
      return Colors.black; // Default color if unrecognized
  }
}

class _DefaultPageState extends State<DefaultPage> {
  late Timer _timer;

  List<MarkerData> markerList = [];

  // fetchMarkerData requests data from the update_map endpoint
  Future<void> fetchMarkerData() async {
    try {
      // Custom HTTP client
      HttpClient client = HttpClient()
        ..badCertificateCallback = // NB: temporary disable SSL certificate validation
            (X509Certificate cert, String host, int port) => true;

      var request =  await client.getUrl(Uri.parse(serverURI+mapEndpoint));
      var response = await request.close();

      // Parse json response to list of MarkerData objects if request is ok
      if (response.statusCode == 200) {
        var responseBody = await response.transform(utf8.decoder).join();
        setState(() {
          markerList = parseMarkerData(responseBody);
        });
      } else {
        print('Request failed with status: ${response.statusCode}');
      }
    } catch (e) {
      print('Failed to connect to the server: $e');
    }
  }

  // Timer initializer
  @override
  void initState() {
    super.initState();
    // Call fetchMarkerData when the widget is first created
    fetchMarkerData();

    // Schedule fetchMarkerData to run periodically based on fetchInterval const
    const Duration fiveMinutes = Duration(minutes: fetchInterval);
    _timer = Timer.periodic(fiveMinutes, (timer) {
      fetchMarkerData();
    });
  }

  // Fetch timer
  @override
  void dispose() {
    // Cancel timer on widget termination
    _timer.cancel();
    super.dispose();
  }

  // Main widget
  @override
  Widget build(BuildContext context) {
    double screenWidth = MediaQuery.of(context).size.width;
    double boxWidth = 0.9;
    double boxHeight = 1.5;
    const double markerSize = 40;

    return Scaffold(
      appBar: AppBar(
        title: const Text('IceMap'),
      ),
      body: Center(
        child: SingleChildScrollView(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Container( // Map container
                width: screenWidth * boxWidth,
                height: screenWidth * boxHeight,
                color: Colors.blue,
                child: FlutterMap(
                  options: MapOptions(
                    center: LatLng(60.7666, 10.8471),
                    zoom: 9.0,
                  ),
                  children: [
                    TileLayer(
                        urlTemplate: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
                        subdomains: const ['a', 'b', 'c'],
                      ),
                    MarkerLayer( // Dynamically allocate markers based on a list
                      markers: markerList
                          .map(
                            (MarkerData markerData) => Marker(
                          width: markerData.size,
                          height: markerData.size,
                          point: markerData.location,
                          builder: (ctx) => Icon(
                            Icons.favorite,
                            color: markerData.color,
                            size: markerData.size,
                          ),
                        ),
                      )
                          .toList(),
                    ),
                  ],
                ),
              ),
              const SizedBox(height: 20),
              Container( // Detailed info container
                width: screenWidth * boxWidth,
                height: screenWidth * boxHeight,
                color: Colors.blue,
                child: const Align(
                  alignment: Alignment.topLeft,
                  child: Padding(
                    padding: EdgeInsets.only(top: 10, left: 10), // Edge padding, text
                    child: Text(
                      'Placeholder text',
                      style: TextStyle(fontSize: 20, color: Colors.black),
                    ),
                  ),
                ),
              ),
              const SizedBox(height: 20),
            ],
          ),
        ),
      ),
    );
  }
}