
import 'package:bus_infotainment/auth/auth_api.dart';
import 'package:bus_infotainment/backend/live_information.dart';
import 'package:bus_infotainment/backend/modules/tracker.dart';
import 'package:bus_infotainment/pages/components/ibus_display.dart';
import 'package:bus_infotainment/pages/home.dart';
import 'package:bus_infotainment/tfl_datasets.dart';
import 'package:bus_infotainment/utils/OrdinanceSurveyUtils.dart';
import 'package:bus_infotainment/utils/delegates.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:dart_ping/dart_ping.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';

import 'package:qr_flutter/qr_flutter.dart';
import 'package:native_qr/native_qr.dart';


import 'package:flutter_carousel_widget/flutter_carousel_widget.dart';
import 'package:geolocator/geolocator.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:shadcn_ui/shadcn_ui.dart';
import 'package:uuid/uuid.dart';
import 'package:vector_math/vector_math.dart' hide Colors;

import '../backend/modules/tube_info.dart';

Color rgb(int r, int g, int b) {
  return Color.fromRGBO(r, g, b, 1);
}



class HomePage_Re extends StatefulWidget {

  @override
  State<HomePage_Re> createState() => _HomePage_ReState();
}

class _HomePage_ReState extends State<HomePage_Re> {
  Future<bool> _shouldRedirectToSetup() async {

    List<bool> perms = [];

    perms.addAll([
      await Permission.manageExternalStorage.isGranted,
      await Permission.location.isGranted
    ]);

    bool shouldRedirectA = !perms.contains(false);
    bool shouldRedirectB = true;

    try {
      Uint8List bytes = await LiveInformation().announcementModule.getBundleBytes();
      shouldRedirectB =  true;
    } catch (e) {
      print("Failed to load bundle");
      shouldRedirectB =  false;
    }

    print("Should redirect to setup: ${shouldRedirectA || shouldRedirectB}");
    print("Permissions: $shouldRedirectA");
    print("Bundle: $shouldRedirectB");
    print("Permissions_indv: $perms");

    return !shouldRedirectA || !shouldRedirectB;
  }


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


    _shouldRedirectToSetup().then((value) {
      if (value) {
        Navigator.pushNamed(context, "/setup");
      }
    });
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      body: Container(

        padding: const EdgeInsets.all(16),

        alignment: Alignment.center,

        child: SizedBox(

          width: double.infinity,

          child: Column(

            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.start,

            children: [

              const Text(
                "Choose mode:",
                style: TextStyle(
                  fontSize: 32,
                  fontWeight: FontWeight.w600,
                )
              ),

              const SizedBox(
                height: 16,
              ),

              ShadCard(
                title: const Text("Solo mode"),
                width: double.infinity,
                description: const Text(
                    "Choose this mode if you are only using this device. (No internet required)"
                ),
                content: Column(

                  crossAxisAlignment: CrossAxisAlignment.start,
                  mainAxisSize: MainAxisSize.min,

                  children: [

                    const SizedBox(
                      height: 4,
                    ),

                    ShadButton.secondary(
                      onPressed: () {
                        Navigator.pushNamed(context, "/routes");
                      },
                      text: const Text("Continue"),
                    )

                  ],
                ),
              ),

              const SizedBox(
                height: 16,
              ),

              ShadCard(
                title: const Text("Multi mode"),
                width: double.infinity,
                description: const Text(
                    "Choose this mode if you are using multiple devices. (Internet required)"
                ),
                content: Column(

                  crossAxisAlignment: CrossAxisAlignment.start,
                  mainAxisSize: MainAxisSize.min,

                  children: [

                    const SizedBox(
                      height: 4,
                    ),

                    ShadButton.secondary(
                      onPressed: () {
                        Navigator.pushNamed(context, "/multi");
                      },
                      text: const Text("Continue"),
                    )

                  ],
                ),
              )



            ],

          ),
        )

      ),
    );
  }

}

class RoutePage extends StatelessWidget {



  @override
  Widget build(BuildContext context) {



    return Scaffold(
      body: Column(
        children: [
          Expanded(
            child: Container(

                padding: const EdgeInsets.all(16),

                alignment: Alignment.center,

                child: SizedBox(

                  width: double.infinity,

                  child: Column(

                    mainAxisSize: MainAxisSize.max,
                    crossAxisAlignment: CrossAxisAlignment.start,

                    children: [

                      Row(
                        children: [

                          Text(
                            "Routes",
                            style: ShadTheme.of(context).textTheme.h1.copyWith(),
                          ),

                          Expanded(
                            child: Container(),
                          ),

                        ],
                      ),
                      if (!kIsWeb)
                      Text(
                        "Nearby routes",
                        style: ShadTheme.of(context).textTheme.h4,
                      ),
                      if (!kIsWeb)
                      FlutterCarousel(
                        options: CarouselOptions(
                          // height: 130,
                          viewportFraction: 0.33,
                          aspectRatio: 3 / 1,
                          enableInfiniteScroll: true,
                          initialPage: 1,
                          autoPlay: true,
                          autoPlayInterval: const Duration(seconds: 2),
                          pauseAutoPlayOnTouch: true,
                          pauseAutoPlayOnManualNavigate: true,
                          showIndicator: false,
                          slideIndicator: const CircularSlideIndicator(),
                          autoPlayAnimationDuration: const Duration(milliseconds: 800),
                          autoPlayCurve: Curves.bounceOut,


                        ),
                        items: [
                          ..._getNearbyRoutes()
                        ],
                      ),

                      const Divider(),

                      RouteSearch(multiMode: false)


                    ],

                  ),
                )

            ),
          ),
          const Divider(
            height: 1,
          ),
          NavigationBar()
        ],
      ),
    );

  }



}

class RouteSearch extends StatefulWidget {

  final bool multiMode;

  RouteSearch({required this.multiMode});

  @override
  State<RouteSearch> createState() => _RouteSearchState();
}

class _RouteSearchState extends State<RouteSearch> {
  TextEditingController controller = TextEditingController();

  @override
  Widget build(BuildContext context) {

    List<Widget> routes = [];

    for (BusRoute route in LiveInformation().busSequences.routes.values.toList()) {

      if (controller.text.isNotEmpty && !route.routeNumber.toLowerCase().contains(controller.text.toLowerCase())) {
        continue;
      }

      routes.add(RouteCard(route: route, multiMode: widget.multiMode));
    }

    return Expanded(
      child: Column(

        children: [

          ShadInput(
            placeholder: const Text("Search for a route..."),
            controller: controller,
            onChanged: (value) {
              setState(() {

              });
            },
          ),

          const SizedBox(
            height: 4,
          ),

          Expanded(
            child: Scrollbar(
              interactive: true,
              radius: const Radius.circular(8),
              thickness: 8,
              thumbVisibility: true,
              child: GridView.count(
                crossAxisCount: 3,
                children: [
                  ...routes
                ],
                shrinkWrap: true,
              ),
            ),
          )

        ],
      ),
    );
  }
}

class RouteCard extends StatelessWidget {

  BusRoute route;
  final bool multiMode;

  RouteCard({required this.route, required this.multiMode});

  @override
  Widget build(BuildContext context) {
    // TODO: implement build

    Map<String, Widget> variants = {};

    for (BusRouteVariant variant in route.routeVariants.values) {
      String variantLabel = "${variant.busStops.first.formattedStopName} -> ${variant.busStops.last.formattedStopName}";

      variants[variantLabel] = ShadOption(
        value: variant.routeVariant.toString(),
        child: Text(variantLabel),
      );
    }

    String rr = "";

    if (route.routeNumber.toLowerCase().startsWith("ul")) {

      rr = "Rail replacement";

      TubeLine? line = LiveInformation().tubeStations.getClosestLine(route.routeVariants.values.first);

      rr = line?.name ?? rr;

      if (!["London Overground", "DLR", "Rail replacement", "Elizabeth Line"].contains(rr)) {
        rr += " line";
      }
      if (rr == "Hammersmith and City line") {
        rr = "Hammersmith & City";
      }

    }



    return AspectRatio(
      aspectRatio: 1,
      child: Container(
        child: ShadButton.secondary(
          text: Column(
            children: [
              Text(
                "Route \n ${route.routeNumber}",
                style: ShadTheme.of(context).textTheme.h3.copyWith(
                  height: 1.1
                )
              ),
              if (route.routeNumber.toLowerCase().startsWith("ul"))
                Text(rr, style: const TextStyle(fontSize: 8))
            ],
          ),
          padding: const EdgeInsets.all(8),
          width: 105,
          height: 105,

          onPressed: () {
            showShadSheet(
                side: ShadSheetSide.bottom,
                context: context,
                builder: (context) {

                  List<Widget> variantWidgets = [];

                  for (BusRouteVariant variant in route.routeVariants.values) {
                    variantWidgets.add(
                        ShadButton.outline(
                          text: SizedBox(
                            width: 800-490,
                            child: Column(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                Text("${variant.busStops.first.formattedStopName} ->"),
                                const SizedBox(
                                  height: 2,
                                ),
                                Text(variant.busStops.last.formattedStopName)
                              ],
                            ),
                          ),
                          width: double.infinity,
                          height: 50,
                          padding: const EdgeInsets.all(8),
                          onPressed: () async {
                            LiveInformation liveInformation = LiveInformation();
                            await liveInformation.setRouteVariant(variant);

                            if (!multiMode) {
                              Navigator.popAndPushNamed(context, "/enroute");
                            } else {
                              // Navigator.popAndPushNamed(context, "/multi/enroute");
                              Navigator.pop(context);
                              ShadToaster.of(context).show(
                                ShadToast(
                                  title: Text("Route selected"),
                                  description: Text("Set route to ${variant.busRoute.routeNumber} - ${variant.busStops.first.formattedStopName} -> ${variant.busStops.last.formattedStopName}"),
                                  duration: Duration(seconds: 5),
                                )
                              );
                            }

                          },
                        )
                    );

                    variantWidgets.add(const SizedBox(
                      height: 4,
                    ));
                  }

                  return ShadSheet(
                    title: Text("Route ${route.routeNumber} - Variants"),

                    content: Container(
                      width: 2000,
                      constraints: const BoxConstraints(
                        maxHeight: 400
                      ),
                      alignment: Alignment.center,
                      child: Scrollbar(
                        thumbVisibility: true,
                        child: SingleChildScrollView(
                          child: Column(
                            children: [
                              ...variantWidgets
                            ],
                          ),
                        ),
                      ),
                    ),
                    padding: const EdgeInsets.all(8),
                  );


                }


            );
          },
        ),
      ),
    );

  }

}

class EnRoutePage extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      body: _dash(),
    );
  }
}

class _dash extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Column(

      children: [

        Container(
            padding: const EdgeInsets.all(8),
            child: ibus_display()
        ),

        const Divider(
          height: 1,
        ),


        ExpandableCarousel(
          items: [
            EasyAnnouncementPicker(
                announcements: LiveInformation().announcementModule.manualAnnouncements,
                title: "Manual"
            ),

            Container(
                padding: const EdgeInsets.all(8),
                child: StopAnnouncementPicker(
                  routeVariant: LiveInformation().getRouteVariant()!,
                  backgroundColor: Colors.transparent,
                  outlineColor: Colors.white,
                  label: "Bus Stops",
                )
            )


          ],
          options: CarouselOptions(
              showIndicator: false

          ),
        ),

        const Divider(
          height: 1,
        ),

        Expanded(
          child: Container(
              padding: const EdgeInsets.all(8),
              child: Column(

                children: [

                  Text(
                    "Quick actions",
                    style: ShadTheme.of(context).textTheme.h3,
                  ),

                  const SizedBox(
                    height: 8,
                  ),

                  Container(
                    decoration: BoxDecoration(
                        color: Colors.transparent,
                        borderRadius: BorderRadius.circular(8),
                        border: Border.all(
                            color: ShadTheme.of(context).colorScheme.primary,
                            width: 1
                        )
                    ),
                    padding: const EdgeInsets.all(4),
                    child: Container(
                      decoration: BoxDecoration(
                          color: Colors.transparent,
                          borderRadius: BorderRadius.circular(4),
                          border: Border.all(
                              color: ShadTheme.of(context).colorScheme.primary,
                              width: 1
                          )
                      ),
                      child: Column(
                        children: [

                          if (!kIsWeb)
                          AnnouncementEntry(
                            label: "Display next stop",
                            index: 0,
                            outlineColor: ShadTheme.of(context).colorScheme.primary,
                            onPressed: () {
                              LiveInformation liveInformation = LiveInformation();
                              TrackerModule trackerModule = liveInformation.trackerModule;

                              BusRouteStop? stop = trackerModule.nearestStop;

                              if (stop != null) {
                                liveInformation.announcementModule.queueAnnounceByAudioName(displayText: stop.formattedStopName);
                              } else {
                                ShadToaster.of(context).show(
                                    const ShadToast(
                                      title: Text("No bus stop found"),
                                      description: Text("No bus stop found nearby"),
                                      duration: Duration(seconds: 5),
                                    )
                                );
                              }
                            },
                          ),

                          Container(
                            height: 1,
                            color: ShadTheme.of(context).colorScheme.primary,
                          ),

                          AnnouncementEntry(
                            label: "Announce destination",
                            index: 1,
                            outlineColor: ShadTheme.of(context).colorScheme.primary,
                            onPressed: () {
                              LiveInformation liveInformation = LiveInformation();
                              liveInformation.announcementModule.queueAnnouncementByRouteVariant(
                                  routeVariant:
                                  liveInformation.getRouteVariant()!
                              );
                            },
                          ),
                        ],
                      ),
                    ),
                  ),

                  SizedBox(
                    height: 8,
                  ),

                  Container(
                    padding: const EdgeInsets.all(8),
                    child: ShadButton(
                      text: const Text("Fullscreen display"),
                      onPressed: () {
                        Navigator.pushNamed(context, "/display");
                      },
                      icon: const Icon(Icons.fullscreen),
                      width: double.infinity,
                    ),
                  ),
                  //
                  // ShadCard(
                  //   title: Text("Stop announcements"),
                  //   width: double.infinity,
                  // ),
                  //
                  // ShadButton(
                  //   text: Text("Route scanner"),
                  //   onPressed: () {
                  //
                  //     LiveInformation liveInformation = LiveInformation();
                  //
                  //     TubeLine? line = liveInformation.tubeStations.getClosestLine(liveInformation.getRouteVariant()!);
                  //
                  //     ShadToaster.of(context).show(
                  //         ShadToast(
                  //           title: Text("Closest line"),
                  //           description: Text(line == null ? "No line found" : line.name),
                  //           duration: Duration(seconds: 5),
                  //         )
                  //     );
                  //
                  //   },
                  // ),
                  //
                  // ShadButton(
                  //   text: Text("dest"),
                  //   onPressed: () {
                  //     LiveInformation liveInformation = LiveInformation();
                  //     liveInformation.announcementModule.queueAnnouncementByRouteVariant(routeVariant: liveInformation.getRouteVariant()!);
                  //   },
                  // ),
                  //
                  // ShadButton(
                  //   text: Text("Open Legacy dashboard"),
                  //   onPressed: () {
                  //     Navigator.pushNamed(context, "/legacy");
                  //   },
                  // )

                ],

              )
          ),
        ),

        const Divider(
          height: 1,
        ),

        NavigationBar()

      ],

    );
  }
}

class EasyAnnouncementPicker extends StatelessWidget {

  late final List<AnnouncementQueueEntry> announcements;

  late final String title;
  Color outlineColor = Colors.white;

  EasyAnnouncementPicker({this.announcements = const [], this.title = "Announcements", this.outlineColor = Colors.white});

  @override
  Widget build(BuildContext context) {

    List<Widget> announcementWidgets = [];

    for (AnnouncementQueueEntry entry in announcements) {
      if (entry is NamedAnnouncementQueueEntry) {
        announcementWidgets.add(
          AnnouncementEntry(
            label: entry.shortName,
            onPressed: () {
              LiveInformation liveInformation = LiveInformation();
              liveInformation.announcementModule.queueAnnouncementByInfoIndex(
                infoIndex: liveInformation.announcementModule.manualAnnouncements.indexOf(entry),
                sendToServer: true
              );

            },
            index: announcements.indexOf(entry),
            outlineColor: outlineColor,

          )
        );
      }

    }

    return AnnouncementPicker(
      announcements: announcementWidgets,
      backgroundColor: const Color(/*Transparent*/0x00000000),
      outlineColor: outlineColor,
      label: title,
    );
  }

}

/*
ShadSelectFormField<String>(
  options: [
    Padding(
      padding: const EdgeInsets.all(8.0),
      child: Text("Choose a variant"),
    ),
    ...variants.values
  ],
  selectedOptionBuilder: (context, value) => value ==
      'none'
      ? const Text('Select a verified email to display')
      : Text(variants.keys.toList()[int.parse(value)-1]!),
  placeholder: Text("Choose a variant"),

),
 */

class MultiModeSetup extends StatefulWidget {

  @override
  State<MultiModeSetup> createState() => _MultiModeSetupState();
}

class _MultiModeSetupState extends State<MultiModeSetup> {

  @override
  void initState() {
    // Check if the user is logged in

    super.initState();


  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(

      body: Column(

        children: [

          Expanded(
            child: Container(

              alignment: Alignment.center,
              padding: const EdgeInsets.all(16),

              child: Column(

                mainAxisSize: MainAxisSize.min,
                crossAxisAlignment: CrossAxisAlignment.start,

                children: [

                  const Text(
                    "Multi mode options:",
                    style: TextStyle(
                      fontSize: 32,
                      fontWeight: FontWeight.w600,
                    )
                  ),

                  const SizedBox(
                    height: 16,
                  ),

                  ShadCard(
                    title: const Text("Host a group"),
                    width: double.infinity,
                    description: const Text(
                        ""
                    ),
                    content: Column(

                      crossAxisAlignment: CrossAxisAlignment.start,
                      mainAxisSize: MainAxisSize.min,

                      children: [

                        const SizedBox(
                          height: 4,
                        ),

                        ShadButton.secondary(
                          onPressed: () async {

                            LiveInformation liveInformation = LiveInformation();

                            Future.delayed(Duration.zero, () {
                              print("At time of loading: ${liveInformation.auth.status}");

                              if (liveInformation.auth.status != AuthStatus.AUTHENTICATED) {
                                Navigator.popAndPushNamed(context, "/multi/login");
                              }
                            });
                            await liveInformation.createRoom(liveInformation.auth.userID!);


                            Navigator.pushNamed(context, "/multi/enroute");
                          },
                          text: const Text("Continue"),
                        )

                      ],
                    ),
                  ),

                  const SizedBox(
                    height: 16,
                  ),

                  ShadCard(
                    title: const Text("Join existing group"),
                    width: double.infinity,
                    description: const Text(
                        ""
                    ),
                    content: Column(

                      crossAxisAlignment: CrossAxisAlignment.start,
                      mainAxisSize: MainAxisSize.min,

                      children: [

                        const SizedBox(
                          height: 4,
                        ),

                        ShadButton.secondary(
                          onPressed: () {
                            Navigator.pushNamed(context, "/multi/join");
                          },
                          text: const Text("Continue"),
                        )

                      ],
                    ),
                  )

                ],

              ),
            ),
          ),

          NavigationBar()




        ],

      )

    );
  }
}

class MultiModeEnroute extends StatefulWidget {

  @override
  State<MultiModeEnroute> createState() => _MultiModeEnrouteState();
}

class _MultiModeEnrouteState extends State<MultiModeEnroute> {

  late final Future<void> roomCodeFuture;

  late ListenerReceipt<BusRouteVariant?> listenerReceipt;

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

    LiveInformation liveInformation = LiveInformation();
    listenerReceipt = liveInformation.routeVariantDelegate.addListener((value) {
      setState(() {

      });
    });

  }

  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
    LiveInformation liveInformation = LiveInformation();
    liveInformation.routeVariantDelegate.removeListener(listenerReceipt);
  }

  @override
  Widget build(BuildContext context) {

    // Set the screen to portrait


    // Generate random uuid
    LiveInformation liveInformation = LiveInformation();


    return PopScope(
      canPop: false,
      onPopInvoked: (didPop) {

        if (didPop){
          print("Compensating for pop");
          liveInformation.leaveRoom();
          return;
        }

        // return;
        // Ask the user to confirm if they want to leave the group
        showShadDialog(
            context: context,
            builder: (context) {
              return ShadDialog(
                title: const Text("Leave group?"),
                content: const Text("Are you sure you want to leave the group?"),
                actions: [
                  ShadButton(
                    text: const Text("Leave"),
                    onPressed: () {
                      liveInformation.leaveRoom();
                      Navigator.pop(context);
                      Navigator.pop(context);
                    },
                  ),
                  ShadButton(
                    text: const Text("Cancel"),
                    onPressed: () {
                      Navigator.pop(context);
                    },
                  )
                ],
              );
            }
        );

      },

      child: Scaffold(

        body: Column(
          children: [
            const Divider(
              height: 1,
            ),

            Container(
              padding: EdgeInsets.all(8),
              child: ibus_display()
            ),

            const Divider(
              height: 1,
            ),

            Container(
              padding: EdgeInsets.all(8),
              child: Text(
                "* Swipe left and right below for more options!",
                textAlign: TextAlign.center,
              ),
            ),

            const Divider(
              height: 1,
            ),

            SizedBox(
              height: 16,
            ),

            Expanded(
              child: FlutterCarousel(
                items: [
                  Container(
                    decoration: BoxDecoration(
                        border: Border.all(
                            color: Colors.white,
                            width: 1
                        ),
                        borderRadius: BorderRadius.circular(8)
                    ),
                    padding: const EdgeInsets.all(4),
                    margin: const EdgeInsets.only(
                      left: 16,
                      right: 16,
                    ),
                    width: double.infinity,

                    child: Column(

                      crossAxisAlignment: CrossAxisAlignment.start,

                      children: [

                        if (!kIsWeb)
                        Container(
                          padding: const EdgeInsets.only(
                            top: 4,
                            left: 8,
                            right: 8,
                            bottom: 4
                          ),
                          child: Text(
                            "Nearby routes",
                            style: ShadTheme.of(context).textTheme.h4,
                          ),
                        ),
                        if (!kIsWeb)
                          Expanded(
                            child: Scrollbar(
                              interactive: true,
                              radius: const Radius.circular(8),
                              thickness: 8,
                              thumbVisibility: true,
                              child: GridView.count(
                                crossAxisCount: 3,
                                children: [
                                  ..._getNearbyRoutes(multiMode: true)
                                ],
                                shrinkWrap: true,
                              ),
                            ),
                          )

                      ],
                    )
                  ),
                  Container(
                      decoration: BoxDecoration(
                          border: Border.all(
                              color: Colors.white,
                              width: 1
                          ),
                          borderRadius: BorderRadius.circular(8)
                      ),
                      padding: const EdgeInsets.all(4),
                      margin: const EdgeInsets.only(
                        left: 16,
                        right: 16,
                      ),

                      child: Expanded(child: RouteSearch(multiMode: true,))
                  ),
                  Container(

                    decoration: BoxDecoration(
                      border: Border.all(
                        width: 1,
                        color: Colors.white
                      ),
                      borderRadius: BorderRadius.all(Radius.circular(8))
                    ),

                    margin: const EdgeInsets.only(
                      left: 16,
                      right: 16,
                    ),

                    padding: EdgeInsets.all(8),

                    child: SingleChildScrollView(
                      child: Column(
                        children: [
                          EasyAnnouncementPicker(
                            announcements: LiveInformation().announcementModule.manualAnnouncements,
                            title: "Manual",
                            outlineColor: ShadTheme.of(context).colorScheme.secondary
                          ),

                          if (liveInformation.getRouteVariant() != null)
                            SizedBox(
                              height: 16,
                            ),

                          if (liveInformation.getRouteVariant() != null)
                            Container(

                                child: StopAnnouncementPicker(
                                  routeVariant: LiveInformation().getRouteVariant()!,
                                  backgroundColor: Colors.transparent,
                                  outlineColor: ShadTheme.of(context).colorScheme.secondary,
                                  label: "Bus Stops",
                                )
                            )
                        ],
                      ),
                    ),
                  ),
                  Container(
                    decoration: BoxDecoration(
                        color: Colors.transparent,
                        borderRadius: BorderRadius.circular(8),
                        border: Border.all(
                            color: ShadTheme.of(context).colorScheme.primary,
                            width: 1
                        )
                    ),
                    margin: const EdgeInsets.only(
                      left: 16,
                      right: 16,
                    ),
                    padding: const EdgeInsets.all(4),
                    child: Container(
                      decoration: BoxDecoration(
                          color: Colors.transparent,
                          borderRadius: BorderRadius.circular(4),
                          border: Border.all(
                              color: ShadTheme.of(context).colorScheme.primary,
                              width: 1
                          )
                      ),
                      child: Column(
                        children: [

                          if (!kIsWeb)
                            AnnouncementEntry(
                              label: "Display next stop",
                              index: 0,
                              outlineColor: ShadTheme.of(context).colorScheme.primary,
                              onPressed: () {
                                LiveInformation liveInformation = LiveInformation();
                                TrackerModule trackerModule = liveInformation.trackerModule;

                                BusRouteStop? stop = trackerModule.nearestStop;

                                if (stop != null) {
                                  liveInformation.announcementModule.queueAnnounceByAudioName(displayText: stop.formattedStopName);
                                } else {
                                  ShadToaster.of(context).show(
                                      const ShadToast(
                                        title: Text("No bus stop found"),
                                        description: Text("No bus stop found nearby"),
                                        duration: Duration(seconds: 5),
                                      )
                                  );
                                }
                              },
                            ),

                          if (!kIsWeb)
                          Container(
                            height: 1,
                            color: ShadTheme.of(context).colorScheme.primary,
                          ),

                          AnnouncementEntry(
                            label: "Announce destination",
                            index: 1,
                            outlineColor: ShadTheme.of(context).colorScheme.primary,
                            onPressed: () {
                              LiveInformation liveInformation = LiveInformation();
                              liveInformation.announcementModule.queueAnnouncementByRouteVariant(
                                  routeVariant:
                                  liveInformation.getRouteVariant()!
                              );
                            },
                          ),

                          Container(
                            height: 1,
                            color: ShadTheme.of(context).colorScheme.primary,
                          ),
                        ],
                      ),
                    ),
                  ),
                ],
                options: CarouselOptions(
                  showIndicator: false,
                  viewportFraction: 1,
                  height: double.infinity,
                  enableInfiniteScroll: true
                ),
              ),
            ),

            Container(
              padding: const EdgeInsets.all(8),
              child: ShadButton(
                text: const Text("Fullscreen display"),
                onPressed: () {
                  Navigator.pushNamed(context, "/display");
                },
                icon: const Icon(Icons.fullscreen),
                width: double.infinity,
              ),
            ),
            const Divider(
              height: 1,
            ),

            Container(
              padding: const EdgeInsets.all(16),

              // height: 200,

              child: ShadCard(
                title: liveInformation.isHost ? const Text("Currently hosting group") : const Text("Successfully joined group"),
                border: Border.all(
                    color: Colors.amber,
                    width: 1
                ),
                padding: const EdgeInsets.all(16),
                width: double.infinity,
                description: liveInformation.isHost ? const Text(
                    "You are hosting a group. \nShare the room code with others to join"
                ) : const Text(
                    "You have joined a group."
                ),
                content: Column(
                  children: [
                    const SizedBox(
                      height: 4,
                    ),

                    FutureBuilder(
                      future: Future.delayed(const Duration(seconds: 1)),
                      builder: (context, snapshot) {
                        return Row(
                          children: [
                            Expanded(
                              child: ShadButton(
                                text: Text(
                                  liveInformation.roomCode!,
                                ),

                                icon: const Icon(Icons.copy),
                                padding: const EdgeInsets.all(8),
                                onPressed: () {
                                  Clipboard.setData(ClipboardData(text: liveInformation.roomCode!));
                                  ShadToaster.of(context).show(
                                      const ShadToast(
                                        title: Text("Copied to clipboard"),
                                        description: Text("Room code copied to clipboard"),
                                        duration: Duration(seconds: 5),
                                      )
                                  );
                                },
                              ),
                            ),
                            ShadButton(
                              icon: const Icon(Icons.qr_code),
                              onPressed: () {
                                showShadDialog(
                                    context: context,
                                    builder: (context) {
                                      return ShadDialog(
                                        title: const Text("QR Code"),
                                        content: Container(

                                          width: 200,
                                          height: 225,

                                          child: Column(
                                            mainAxisSize: MainAxisSize.min,
                                            children: [
                                              QrImageView(
                                                data: liveInformation.roomCode!,
                                                size: 200,
                                                backgroundColor: Colors.white,
                                              ),

                                              const SizedBox(
                                                height: 8,
                                              ),

                                              Text("Scan QR code to join the group")

                                            ],
                                          ),
                                        ),
                                        actions: [
                                          ShadButton(
                                            text: const Text("Close"),
                                            onPressed: () {
                                              Navigator.pop(context);
                                            },
                                          )
                                        ],
                                      );
                                    }
                                );
                              },
                            )
                          ],
                        );
                      },
                    ),
                  ],
                ),
              ),
            ),

            const Divider(
              height: 1,
            ),
            NavigationBar()
          ],
        ),

      ),
    );
  }


}

class MultiModeJoin extends StatefulWidget {

  @override
  State<MultiModeJoin> createState() => _MultiModeJoinState();
}

class _MultiModeJoinState extends State<MultiModeJoin> {
  TextEditingController controller = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          Expanded(
            child: Container(

              alignment: Alignment.center,
              padding: EdgeInsets.all(16),

              child: Column(

                mainAxisSize: MainAxisSize.min,

                children: [
                  ShadCard(
                    title: const Text("Join a group"),
                    width: double.infinity,
                    description: const Text("Enter the room code to join a group"),
                    content: Column(
                      children: [
                        ShadInputFormField(
                          controller: controller,
                          id: "roomCode",
                          label: const Text("Room code"),
                          placeholder: const Text("Enter the room code"),
                          validator: (value) {
                            if (value.isEmpty) {
                              return "Please enter the room code";
                            }
                            return null;
                          },
                        ),
                        ShadButton(
                          text: const Text("Join"),
                          width: double.infinity,
                          onPressed: () async {
                            LiveInformation liveInformation = LiveInformation();

                            liveInformation.setRouteVariant(null);

                            await liveInformation.joinRoom(controller.text);

                            Navigator.popAndPushNamed(context, "/multi/enroute");

                          },
                        )
                      ],
                    ),
                  ),
                  const SizedBox(
                    height: 16,
                  ),
                  ShadButton.secondary(
                    text: Text("Scan QR code"),
                    icon: const Icon(Icons.qr_code),
                    onPressed: () async {
                      try {
                        NativeQr nativeQr = NativeQr();
                        String? result = await nativeQr.get();
                        controller.text = result!;
                      } catch (e) {
                        print("Failed to scan QR code");
                      }
                    }
                  )
                  // ibus_display(),
                  // Expanded(child: _dash())
                ]
              ),
            ),
          ),
          Divider(
            height: 1
          ),
          NavigationBar()
        ],
      ),
    );
  }
}

class FullscreenDisplay extends StatefulWidget {

  @override
  State<FullscreenDisplay> createState() => _FullscreenDisplayState();
}

class _FullscreenDisplayState extends State<FullscreenDisplay> {



  @override
  Widget build(BuildContext context) {

    // Get the current screen orientation
    final Orientation orientation = MediaQuery.of(context).orientation;


    // Make the screen landscape
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.landscapeRight,
      DeviceOrientation.landscapeLeft
    ]);

    return PopScope(
      onPopInvoked: (isPop) {
        if (isPop) {
          // SystemChrome.setPreferredOrientations([
          //   DeviceOrientation.portraitUp,
          //   DeviceOrientation.portraitDown
          // ]);

          // Set the orientation back to whatever it was before
          SystemChrome.setPreferredOrientations(orientation == Orientation.portrait ? [
            DeviceOrientation.portraitUp,
            DeviceOrientation.portraitDown
          ] : [
            DeviceOrientation.landscapeRight,
            DeviceOrientation.landscapeLeft
          ]);
        }
      },
      child: Scaffold(

        body: Container(

          color: Colors.black,
          alignment: Alignment.center,

          child: Row(
            children: [
              Expanded(
                child: ibus_display(
                  hasBorder: false,
                ),
              ),
              Container(

                alignment: Alignment.bottomRight,

                child: ShadButton.ghost(
                  icon: const Icon(Icons.arrow_back),
                  padding: const EdgeInsets.all(8),
                  onPressed: () {
                    Navigator.pop(context);
                  },
                ),
              )
            ],
          ),

        ),

      ),
    );
  }
}

class MultiModeLogin extends StatelessWidget {

  final formKey = GlobalKey<ShadFormState>();

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(

      body: Column(
        children: [
          Expanded(
            child: Container(

              padding: const EdgeInsets.all(16),
              alignment: Alignment.centerLeft,

              child: Column(

                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisSize: MainAxisSize.min,

                children: [

                  Text(
                    "Login",
                    style: ShadTheme.of(context).textTheme.h2,
                  ),

                  ShadForm(
                    key: formKey,
                    child: Column(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        ShadInputFormField(
                          id: "email",
                          label: const Text("Email"),
                          autofillHints: const [AutofillHints.email],
                          placeholder: const Text("Enter your email"),
                          validator: (value) {
                            if (value.isEmpty) {
                              return "Please enter your email";
                            }
                            if (!value.contains("@")) {
                              return "Please enter a valid email";
                            }
                            return null;
                          },
                        ),
                        ShadInputFormField(
                          id: "password",
                          label: const Text("Password"),
                          placeholder: const Text("Enter your password"),
                          autofillHints: const [AutofillHints.password],
                          obscureText: true,
                          validator: (value) {
                            if (value.isEmpty) {
                              return "Please enter your password";
                            }
                            if (value.length < 8) {
                              return "Password must be at least 8 characters long";
                            }
                            return null;
                          },
                        )
                      ],
                    ),
                  ),

                  ShadButton(
                    text: const Text("Login"),
                    width: double.infinity,
                    onPressed: () async {
                      if (formKey.currentState!.validate()) {
                        formKey.currentState!.save();
                        print("Logging in...");

                        LiveInformation liveInformation = LiveInformation();
                        await liveInformation.auth.createEmailSession(
                          email: formKey.currentState!.value["email"],
                          password: formKey.currentState!.value["password"]
                        );
                        print("Done something");
                        print(liveInformation.auth.status);
                      }
                    },
                  ),

                  Row(
                    mainAxisSize: MainAxisSize.max,
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      const Text("Don't have an account?"),
                      ShadButton.link(
                        onPressed: () {
                          Navigator.pushNamed(context, "/multi/register");
                        },
                        text: const Text("Register"),
                      )
                    ],
                  )

                ],

              ),

            ),
          ),
          const Divider(
            height: 1,
          ),
          NavigationBar()
        ],
      ),

    );
  }

}

class MultiModeRegister extends StatelessWidget {

  final formKey = GlobalKey<ShadFormState>();

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(

      body: Column(
        children: [
          Expanded(
            child: Container(

              padding: const EdgeInsets.all(16),
              alignment: Alignment.centerLeft,

              child: SingleChildScrollView(
                child: Column(

                  crossAxisAlignment: CrossAxisAlignment.start,
                  mainAxisSize: MainAxisSize.min,

                  children: [

                    Text(
                      "Register",
                      style: ShadTheme.of(context).textTheme.h2,
                    ),

                    ShadForm(
                      key: formKey,
                      child: Column(
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          ShadInputFormField(
                            id: "email",
                            label: const Text("Email"),
                            autofillHints: const [AutofillHints.email],
                            placeholder: const Text("Enter your email"),
                            validator: (value) {
                              if (value.isEmpty) {
                                return "Please enter your email";
                              }
                              if (!value.contains("@")) {
                                return "Please enter a valid email";
                              }
                              return null;
                            },
                          ),
                          ShadInputFormField(
                            id: "password",
                            label: const Text("Password"),
                            placeholder: const Text("Enter your password"),
                            autofillHints: const [AutofillHints.password],
                            obscureText: true,
                            validator: (value) {
                              if (value.isEmpty) {
                                return "Please enter your password";
                              }
                              if (value.length < 8) {
                                return "Password must be at least 8 characters long";
                              }
                              return null;
                            },
                          ),
                          ShadInputFormField(
                            id: "confirmPassword",
                            label: const Text("Confirm password"),
                            placeholder: const Text("Re-enter your password"),
                            autofillHints: const [AutofillHints.password],
                            obscureText: true,
                            validator: (value) {
                              if (value.isEmpty) {
                                return "Please enter your password";
                              }
                              if (value.length < 8) {
                                return "Password must be at least 8 characters long";
                              }
                              if (value != formKey.currentState!.value["password"]) {
                                return "Passwords do not match";
                              }
                              return null;
                            },
                          )
                        ],
                      ),
                    ),

                    ShadButton(
                      text: const Text("Register"),
                      width: double.infinity,
                      onPressed: () async {
                        if (formKey.currentState!.validate()) {
                          formKey.currentState!.save();
                          print("Logging in...");

                          LiveInformation liveInformation = LiveInformation();
                          await liveInformation.auth.createUser(
                            displayName: formKey.currentState!.value["email"],
                            username: formKey.currentState!.value["email"],
                            email: formKey.currentState!.value["email"],
                            password: formKey.currentState!.value["password"],
                          );
                          await liveInformation.auth.createEmailSession(
                              email: formKey.currentState!.value["email"],
                              password: formKey.currentState!.value["password"]
                          );
                          if (liveInformation.auth.status == AuthStatus.AUTHENTICATED) {
                            Navigator.pop(context);
                            Navigator.popAndPushNamed(context, "/multi");
                          } else {
                            ShadToaster.of(context).show(
                              const ShadToast(
                                title: Text("Failed to register"),
                                description: Text("Failed to register with the provided details"),
                                duration: Duration(seconds: 5),
                              )
                            );
                          }
                        }
                      },
                    ),

                    Row(
                      mainAxisSize: MainAxisSize.max,
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        const Text("Have an account?"),
                        ShadButton.link(
                          onPressed: () {
                            Navigator.pushNamed(context, "/multi/login");
                          },
                          text: const Text("Login"),
                        )
                      ],
                    )

                  ],

                ),
              ),

            ),
          ),
          const Divider(
            height: 1,
          ),
          NavigationBar()
        ],
      ),

    );
  }

}

class NavigationBar extends StatefulWidget {

  final Widget? content;

  NavigationBar({this.content = null});

  @override
  State<NavigationBar> createState() => _NavigationBarState();
}

class _NavigationBarState extends State<NavigationBar> {
  @override
  Widget build(BuildContext context) {

    // Is the on screen keyboard visible?
    bool isKeyboardVisible = MediaQuery.of(context).viewInsets.bottom > 0;
    if (isKeyboardVisible) {
      return Container();
    }

    return Row(
      children: [
        ShadButton.ghost(
          onPressed: () {
            Navigator.pop(context);
          },
          icon: const Icon(Icons.arrow_back),
          text: const Text("Back"),
          padding: const EdgeInsets.all(8),
        ),

      ],
    );
  }
}

List<Widget> _getNearbyRoutes({bool multiMode = false}) {

  print("Getting nearby routes");

  LiveInformation liveInformation = LiveInformation();
  BusSequences busSequences = liveInformation.busSequences;

  List<BusRoute> nearbyRoutes = [];

  Position? currentLocation = liveInformation.trackerModule.position;

  Vector2 currentVector = Vector2(0, 0);

  if (currentLocation == null && !kDebugMode) {
    return [];
  } else if (currentLocation != null){
    currentVector = OSGrid.toNorthingEasting(currentLocation!.latitude, currentLocation.longitude);
  }



  if (kDebugMode) {
    // currentVector = OSGrid.toNorthingEasting(51.583781262560926, -0.020359583104595073);
  }

  for (BusRoute route in busSequences.routes.values) {
    for (BusRouteVariant variant in route.routeVariants.values) {
      for (BusRouteStop stop in variant.busStops) {

        Vector2 stopVector = Vector2(stop.easting.toDouble(), stop.northing.toDouble());

        double distance = currentVector.distanceTo(stopVector);

        if (distance < 1000) {
          nearbyRoutes.add(route);
          break;
        }
      }
      if (nearbyRoutes.contains(route)) {
        break;
      }
    }
    if (nearbyRoutes.contains(route)) {
      continue;
    }
  }

  List<Widget> routeCards = [];

  for (BusRoute route in nearbyRoutes) {
    routeCards.add(RouteCard(route: route, multiMode: multiMode));
  }

  return routeCards;

}