

import 'package:bus_infotainment/utils/OrdinanceSurveyUtils.dart';
import 'package:bus_infotainment/utils/audio%20wrapper.dart';
import 'package:vector_math/vector_math.dart';

import '../../tfl_datasets.dart';

class TubeStations {

  List<TubeStation> stations = [];
  List<TubeLine> lines = [];

  TubeStations.fromJson(Map<String, dynamic> json) {
    /*
      Example:
      "Acton Town": {
        "lines": [
            "District",
            "Piccadilly"
        ],
        "location": {
            "lat": 51.5029984,
            "lng": -0.2803455
        }
    },
     */

    for (String stationName in json.keys) {
      TubeStation station = TubeStation();
      station.name = stationName;

      Map<String, dynamic> stationData = json[stationName];

      station.latitude = stationData["location"]["lat"];
      station.longitude = stationData["location"]["lng"];

      for (String lineName in stationData["lines"]) {

        // check if the line already exists
        TubeLine line = lines.firstWhere((element) => element.name == lineName, orElse: () => TubeLine()..name = lineName);

        if (!lines.contains(line)) {
          lines.add(line);
        }

        station.lines.add(line);
      }

      stations.add(station);
    }

  }

  // Get the london underground line that is a close match to a given bus route variant
  TubeLine? getClosestLine(BusRouteVariant variant) {

    Map<TubeLine, int> lineMatches = {};

    for (TubeLine line in lines) {
      lineMatches[line] = 0;
    }

    for (BusRouteStop stop in variant.busStops) {
      for (TubeStation station in stations) {

        // get the distance between the bus stop and the tube station
        double distance = Vector2(stop.easting.toDouble(), stop.northing.toDouble()).distanceTo(OSGrid.toNorthingEasting(station.latitude, station.longitude));

        // if the distance is less than 100m, then we can assume that the bus stop is near the tube station
        if (distance < 400) {
          for (TubeLine line in station.lines) {
            lineMatches[line] = lineMatches[line]! + 1;
          }
        }
      }
    }

    TubeLine? closestLine;
    int closestMatch = 0;
    for (TubeLine line in lineMatches.keys) {
      if (lineMatches[line]! > closestMatch) {
        closestLine = line;
        closestMatch = lineMatches[line]!;
      }
    }

    return closestLine;

  }

}

class TubeStation {

  late final String name;

  late final double latitude;
  late final double longitude;

  List<TubeLine> lines = [];

}

class TubeLine {

  late final String name;

  AudioWrapperSource? getAudio() {

    String lineName = name.toLowerCase().replaceAll(" ", "_");
    lineName = lineName.replaceAll("and", "N");
    lineName = lineName.toUpperCase();

    return AudioWrapperAssetSource("audio/rail_replacement/$lineName.mp3");
  }

  // Get short name
// example: "District" -> "DIS", "London Overground" -> "LO", "TfL Rail" -> "TFL", "Waterloo and City" -> "W&C"
  String getShortName() {
    String shortName = name;

    List<String> words = shortName.split(" ");
    shortName = words.map((e) => e[0]).join("");

    if (shortName.length < 3) {
      shortName = name.substring(0, 3).toUpperCase();
    }

    return shortName;
  }

}