import 'dart:convert';

import 'package:blind_master/BlindMasterResources/blind_control_widget.dart';
import 'package:blind_master/BlindMasterResources/blindmaster_progress_indicator.dart';
import 'package:blind_master/BlindMasterResources/error_snackbar.dart';
import 'package:blind_master/BlindMasterResources/secure_transmissions.dart';
import 'package:blind_master/BlindMasterResources/text_inputs.dart';
import 'package:blind_master/BlindMasterResources/timezone_picker.dart';
import 'package:blind_master/BlindMasterScreens/schedules_screen.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:socket_io_client/socket_io_client.dart' as IO;

class PeripheralScreen extends StatefulWidget {
  const PeripheralScreen({super.key, required this.peripheralId, required this.deviceId, required this.peripheralNum, required this.deviceName, this.isSinglePort = false});
  final int peripheralId;
  final int peripheralNum;
  final int deviceId;
  final String deviceName;
  final bool isSinglePort;
  @override
  State<PeripheralScreen> createState() => _PeripheralScreenState();
}

class _PeripheralScreenState extends State<PeripheralScreen> {
  IO.Socket? socket;
  String imagePath = "";
  late String _deviceName;
  String peripheralName = "...";
  bool loaded = false;
  bool calibrated = false;
  bool calibrating = false;
  bool deviceConnected = true; // Track device connection status
  int calibrationStage = 0; // 0=not started, 1=tilt up, 2=tilt down
  double _blindPosition = 5.0;
  DateTime? lastSet;
  String lastSetMessage = "";
  int? batterySoc;
  bool _movementPending = false;
  bool _awaitingDeviceWake = false;

  String? _deviceTimezone;

  final _peripheralRenameController = TextEditingController();

  void getImage() {
    final hour = DateTime.now().hour;

    if (hour >= 5 && hour < 10) {
      imagePath = 'assets/images/MorningSill.png';
    } else if (hour >= 10 && hour < 18) {
      imagePath = 'assets/images/NoonSill.png';
    } else if (hour >= 18 && hour < 22) {
      imagePath = 'assets/images/EveningSill.png';
    } else {
      imagePath = 'assets/images/NightSill.png';
    }
  }

  @override
  void initState() {
    super.initState();
    _deviceName = widget.deviceName;
    initAll();
    initSocket();
  }

  @override
  void dispose() {
    socket?.disconnect();
    socket?.dispose();
    super.dispose();
  }

  Future<void> initSocket() async {
    try {
      socket = await connectSocket();
      if (socket == null) throw Exception("Unsuccessful socket connection");
      
      // Handle rate limiting errors
      socket?.on("error", (data) async {
        if (data is Map<String, dynamic>) {
          if (data['code'] == 429) {
            // Rate limited - wait and reconnect
            print("Rate limited: ${data['message']}. Reconnecting in 1 second...");
            socket?.disconnect();
            socket?.dispose();
            await Future.delayed(const Duration(seconds: 1));
            if (mounted) {
              initSocket();
            }
          }
        }
      });
      
      socket?.on("success", (_) {
        socket?.on("device_connected", (data) {
          if (data is Map<String, dynamic>) {
            if (data['deviceID'] == widget.deviceId) {
              if (!mounted) return;
              setState(() {
                deviceConnected = true;
              });
            }
          }
        });
        
        socket?.on("device_disconnected", (data) {
          if (data is Map<String, dynamic>) {
            if (data['deviceID'] == widget.deviceId) {
              if (!mounted) return;
              setState(() {
                deviceConnected = false;
                // Reset calibration if it was in progress
                if (calibrating) {
                  calibrationStage = 0;
                }
              });
            }
          }
        });
        
        socket?.on("posUpdates", (list) {
          for (var update in list) {
            if (update is Map<String, dynamic>) {
              if (update['periphID'] == widget.peripheralId) {
                if (!mounted) return;
                setState(() {
                  _blindPosition = (update['pos'] as int).toDouble();
                });
              }
            }
          }
        });
        
        socket?.on("battery_alert", (data) {
          if (data is! Map<String, dynamic>) return;
          if (data['deviceId'] != widget.deviceId) return;
          if (!mounted) return;
          final type = data['type'] as String? ?? '';
          final soc  = data['soc']  as int?    ?? 0;
          setState(() => batterySoc = soc);
          final (String message, Color color) = switch (type) {
            'overvoltage'          => ('Battery fault detected. Please check your charger.', Colors.red),
            'critical_low'        => ('Battery critically low ($soc%). Device shutting down.', Colors.red),
            'low_voltage_warning' => ('Battery voltage dip detected ($soc%). Monitor closely.', Colors.orange),
            'low_20'              => ('Battery low: $soc% remaining. Consider charging soon.', Colors.orange),
            'low_10'              => ('Battery very low: $soc% remaining. Charge now.', Colors.deepOrange),
            _                     => ('Battery alert received ($soc%).', Colors.orange),
          };
          ScaffoldMessenger.of(context).showSnackBar(SnackBar(
            content: Text(message),
            backgroundColor: color,
            duration: const Duration(seconds: 6),
          ));
        });

        // Server emits this when the device reports its own calibration state.
        // When calibrated=false, reset all calibration UI state so the
        // pre-calibration screen is shown and the user can tap Calibrate.
        socket?.on("calib_status_changed", (data) {
          if (data is Map<String, dynamic>) {
            if (data['periphID'] == widget.peripheralId) {
              if (!mounted) return;
              if (data['calibrated'] == false) {
                final wasAwaiting = _awaitingDeviceWake;
                setState(() {
                  calibrated = false;
                  calibrating = false;
                  calibrationStage = 0;
                  _awaitingDeviceWake = false;
                });
                if (wasAwaiting) calibrate();
              }
            }
          }
        });

        socket?.on("device_pos_report", (data) {
          if (data is Map<String, dynamic>) {
            if (data['periphID'] == widget.peripheralId) {
              if (!mounted) return;
              setState(() {
                _blindPosition = (data['pos'] as int).toDouble();
                _movementPending = false;
              });
            }
          }
        });

        socket?.on("calib", (periphData) {
          if (periphData is Map<String, dynamic>) {
            if (periphData['periphID'] == widget.peripheralId) {
              if (!mounted) return;
              setState(() {
                calibrating = true;
                calibrated = false;
                calibrationStage = 0; // Waiting for device to be ready
              });
            }
          }
        });
        
        socket?.on("calib_error", (errorData) {
          if (errorData is Map<String, dynamic>) {
            if (errorData['periphID'] == widget.peripheralId) {
              if (!mounted) return;
              setState(() {
                calibrating = false;
                calibrationStage = 0;
              });
              ScaffoldMessenger.of(context).showSnackBar(
                SnackBar(
                  content: Text(errorData['message'] ?? 'Calibration error'),
                  backgroundColor: Colors.red,
                )
              );
            }
          }
        });
        
        socket?.on("calib_stage1_ready", (periphData) {
          if (periphData is Map<String, dynamic>) {
            if (periphData['periphID'] == widget.peripheralId) {
              if (!mounted) return;
              setState(() {
                calibrationStage = 1; // Device ready for tilt up
              });
            }
          }
        });
        
        socket?.on("calib_stage2_ready", (periphData) {
          if (periphData is Map<String, dynamic>) {
            if (periphData['periphID'] == widget.peripheralId) {
              if (!mounted) return;
              setState(() {
                calibrationStage = 2; // Device ready for tilt down
              });
            }
          }
        });
        
        socket?.on("calib_done", (periphData) {
          if (periphData is Map<String, dynamic>) {
            if (periphData['periphID'] == widget.peripheralId) {
              if (!mounted) return;
              setState(() {
                calibrating = false;
                calibrated = true;
                calibrationStage = 0;
              });
              // Fetch updated peripheral data after calibration completes
              fetchState();
            }
          }
        });
      });
    } catch (e) {
      if (mounted) ScaffoldMessenger.of(context).showSnackBar(errorSnackbar(e));
    }
  }

  Future<void> calibrate() async {
    if (!deviceConnected) {
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(
          content: Text('Device must be connected to calibrate'),
          backgroundColor: Colors.orange,
        )
      );
      return;
    }
    
    try {
      final payload = {
        'periphId': widget.peripheralId
      };

      final response = await securePost(payload, 'calib');
      
      if (response == null) throw Exception("auth error");
      if (response.statusCode != 202) throw Exception("Server Error");
      calibrated = false;
    } catch (e) {
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(errorSnackbar(e));
    }
  }

  Future<void> cancelCalib() async {
    try {
      final payload = {
        'periphId': widget.peripheralId
      };

      final response = await securePost(payload, 'cancel_calib');
      
      if (response == null) throw Exception("auth error");
      if (response.statusCode != 202) throw Exception("Server Error");
      
      // Only update state if cancel succeeded
      if (!mounted) return;
      setState(() {
        calibrated = false;
        calibrating = false;
        calibrationStage = 0;
      });
    } catch (e) {
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(errorSnackbar(e));
    }
  }

  Future<void> completeStage1() async {
    // User confirms they've tilted blinds all the way up
    // Tell device to proceed to stage 2
    socket?.emit("user_stage1_complete", {
      "periphID": widget.peripheralId,
      "periphNum": widget.peripheralNum,
      "deviceID": widget.deviceId
    });
    setState(() {
      calibrationStage = 0; // Wait for device acknowledgment
    });
  }

  Future<void> completeStage2() async {
    // User confirms they've tilted blinds all the way down
    // Tell device calibration is complete
    socket?.emit("user_stage2_complete", {
      "periphID": widget.peripheralId,
      "periphNum": widget.peripheralNum,
      "deviceID": widget.deviceId
    });
    setState(() {
      calibrationStage = 0; // Wait for device acknowledgment
    });
  }

  Future<void> getName() async {
    try {
      final payload = {
        'periphId': widget.peripheralId
      };
      final response = await secureGet('peripheral_name', queryParameters: payload);
      if (response == null) throw Exception("auth error");
      if (response.statusCode != 200) throw Exception("Server Error");
      final body = json.decode(response.body);
      setState(() => peripheralName = body['name']);
    } catch (e) {
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(errorSnackbar(e));
    }
  }

  Future<void> getDeviceBatterySoc() async {
    try {
      final payload = {'deviceId': widget.deviceId};
      final response = await secureGet('device_name', queryParameters: payload);
      if (response == null) throw Exception("auth error");
      if (response.statusCode != 200) throw Exception("Server Error");
      final body = json.decode(response.body);
      if (!mounted) return;
      setState(() {
        batterySoc = body['battery_soc'] as int?;
        _deviceTimezone = body['timezone'] as String?;
      });
    } catch (e) {
      // Non-critical; swallow silently
    }
  }

  Future<void> updateDeviceTimezone(String timezone) async {
    try {
      final response = await securePost(
        {'deviceId': widget.deviceId, 'timezone': timezone},
        'update_device_timezone',
      );
      if (response == null) throw Exception("Auth Error");
      if (response.statusCode != 200) throw Exception("Server Error");
      if (!mounted) return;
      setState(() => _deviceTimezone = timezone);
    } catch (e) {
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(errorSnackbar(e));
    }
  }

  Future<void> checkDeviceConnection() async {
    try {
      final payload = {
        'deviceId': widget.deviceId
      };
      final response = await secureGet('device_connection_status', queryParameters: payload);
      if (response == null) throw Exception("auth error");
      if (response.statusCode != 200) throw Exception("Server Error");
      final body = json.decode(response.body);
      if (!mounted) return;
      setState(() => deviceConnected = body['connected']);
    } catch (e) {
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(errorSnackbar(e));
    }
  }

  Future fetchState() async{
    try {
      final payload = {
        'periphId': widget.peripheralId
      };

      final response = await secureGet('peripheral_status', queryParameters: payload);
      if (response == null) throw Exception("auth error");
      if (response.statusCode != 200) {
        if (response.statusCode == 404) throw Exception("Device Not Found");
        throw Exception("Server Error");
      }
      final body = json.decode(response.body) as Map<String, dynamic>;
      if (!body['await_calib']){
        if (!body['calibrated']) {
          calibrated = false;
          calibrating = false;
        }
        else {
          getImage();
          
          if (body['last_set'] != null) {
            final nowUtc = DateTime.now().toUtc();
            final lastSetUtc = DateTime.parse(body['last_set']);
            final Duration difference = nowUtc.difference(lastSetUtc);
            if (!lastSetUtc.isUtc) throw Exception("Why isn't the server giving UTC?");
            final diffDays = difference.inDays > 0;
            final diffHours = difference.inHours > 0;
            final diffMins = difference.inMinutes > 0;
            lastSetMessage = "Last set ${diffDays ? '${difference.inDays.toString()} days' : diffHours ? '${difference.inHours.toString()} hours' : diffMins ? '${difference.inMinutes.toString()} minutes' : '${difference.inSeconds.toString()} seconds'} ago";
          } else {
            lastSetMessage = "Never set";
          }
          
          _blindPosition = (body['last_pos'] as int).toDouble();

          calibrated = true;
          calibrating = false;
        }
      }
      else {
        calibrating = true;
      }
      
      setState(() {loaded = true;});
    } catch (e) {
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(errorSnackbar(e));
    }
  }

  Future initAll() async{
    getName();
    checkDeviceConnection();
    fetchState();
    getDeviceBatterySoc();
  }

  void rename() {
    String? dialogTimezone = _deviceTimezone;
    showDialog(
      context: context,
      builder: (BuildContext dialogContext) {
        return StatefulBuilder(
          builder: (context, setDialogState) {
            return AlertDialog(
              title: Text(
                widget.isSinglePort ? "Rename Device" : "Rename Peripheral",
                style: GoogleFonts.aBeeZee(),
              ),
              content: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  BlindMasterMainInput(
                    widget.isSinglePort
                        ? "New Device Name (blank to keep current)"
                        : "New Peripheral Name (blank to keep current)",
                    controller: _peripheralRenameController,
                  ),
                  if (widget.isSinglePort) ...[
                    const SizedBox(height: 16),
                    TimezonePicker(
                      value: dialogTimezone,
                      label: 'Device Timezone (blank to keep current)',
                      onChanged: (tz) => setDialogState(() => dialogTimezone = tz),
                    ),
                  ],
                ],
              ),
              actions: [
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  children: [
                    ElevatedButton(
                      onPressed: () => Navigator.of(dialogContext).pop(),
                      child: const Text(
                        "Cancel",
                        style: TextStyle(color: Colors.red),
                      ),
                    ),
                    ElevatedButton(
                      onPressed: () {
                        final newName = _peripheralRenameController.text.trim();
                        if (widget.isSinglePort) {
                          if (newName.isNotEmpty) updateDeviceName(newName);
                          if (dialogTimezone != null) updateDeviceTimezone(dialogTimezone!);
                        } else {
                          if (newName.isNotEmpty) updatePeriphName(newName, widget.peripheralId);
                        }
                        Navigator.of(dialogContext).pop();
                      },
                      child: const Text("Confirm"),
                    ),
                  ],
                ),
              ],
            );
          },
        );
      },
    );
  }

  Future updateDeviceName(String name) async {
    try {
      if (name.isEmpty) throw Exception("New name cannot be empty!");
      final payload = {
        'deviceId': widget.deviceId,
        'newName': name,
      };
      final response = await securePost(payload, 'rename_device');
      if (response == null) throw Exception("Auth Error");
      if (response.statusCode != 204) {
        if (response.statusCode == 409) throw Exception("Choose a unique name!");
        throw Exception("Server Error");
      }
      if (!mounted) return;
      setState(() => _deviceName = name);
    } catch (e) {
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(errorSnackbar(e));
    }
  }

  Future updatePeriphName(String name, int id) async {
    try {
      if (name.isEmpty) throw Exception("New name cannot be empty!");
      final payload = {
        'periphId': id,
        'newName': name,
      };
      final response = await securePost(payload, 'rename_peripheral');
      if (response == null) throw Exception("Auth Error");
      if (response.statusCode != 204) {
        if (response.statusCode == 409) throw Exception("Choose a unique name!");
        throw Exception("Server Error");
      }
      getName();
    } catch (e) {
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(errorSnackbar(e));
    }
  }

  void recalibrate() {
    showDialog(
      context: context,
      builder: (BuildContext dialogContext) {
        return AlertDialog(
          title: Text(
            "Recalibrate Peripheral",
            style: GoogleFonts.aBeeZee(),
          ),
          content: const Text(
            "After confirming, wake the device by moving the wand. Calibration will start automatically.",
            textAlign: TextAlign.center,
          ),
          actions: [
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: [
                ElevatedButton(
                  onPressed: () {
                    Navigator.of(dialogContext).pop();
                  },
                  child: const Text(
                    "Cancel",
                    style: TextStyle(color: Colors.red),
                  )
                ),
                ElevatedButton(
                  onPressed: () {
                    Navigator.of(dialogContext).pop();
                    socket?.emit("recalibrate", {
                      "periphID": widget.peripheralId,
                      "periphNum": widget.peripheralNum,
                    });
                    setState(() => _awaitingDeviceWake = true);
                  },
                  child: const Text("Confirm")
                )
              ],
            )
          ],
        );
      }
    );
  }

  Future updateBlindPosition() async {
    try {
      final payload = {
        'periphId': widget.peripheralId,
        'periphNum': widget.peripheralNum,
        'deviceId': widget.deviceId,
        'newPos': _blindPosition.toInt(),
      };

      final response = await securePost(payload, 'manual_position_update');
      if (response == null) throw Exception("Auth Error");
      if (response.statusCode != 202) {
        throw Exception("Server Error");
      }
    } catch (e) {
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(errorSnackbar(e));
    }
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomInset: false,
      appBar: AppBar(
        title: Text(
          widget.isSinglePort ? _deviceName : "$_deviceName - $peripheralName",
          style: GoogleFonts.aBeeZee(),
        ),
        backgroundColor: Theme.of(context).primaryColorLight,
        foregroundColor: Colors.white,
        actions: [
          if (batterySoc != null)
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 16),
              child: Row(
                children: [
                  Icon(
                    batterySoc! <= 10 ? Icons.battery_alert
                    : batterySoc! <= 20 ? Icons.battery_1_bar
                    : batterySoc! <= 40 ? Icons.battery_2_bar
                    : batterySoc! <= 60 ? Icons.battery_3_bar
                    : batterySoc! <= 80 ? Icons.battery_5_bar
                    : Icons.battery_full,
                    color: batterySoc! <= 10 ? Colors.red : Colors.white,
                  ),
                  const SizedBox(width: 4),
                  Text('$batterySoc%', style: const TextStyle(color: Colors.white)),
                ],
              ),
            ),
        ],
      ),

      body: Column(
        children: [
          if (_movementPending)
            Container(
              width: double.infinity,
              padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
              color: Colors.orange.shade700,
              child: Row(
                children: [
                  const Icon(Icons.access_time, color: Colors.white, size: 20),
                  const SizedBox(width: 12),
                  const Expanded(
                    child: Text(
                      'Movement pending... Will take up to 1 minute',
                      style: TextStyle(color: Colors.white, fontSize: 14, fontWeight: FontWeight.w500),
                    ),
                  ),
                ],
              ),
            ),
          Expanded(child: _awaitingDeviceWake
          ? Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  CircularProgressIndicator(color: Theme.of(context).primaryColorLight),
                  const SizedBox(height: 24),
                  Text(
                    "Wake the device by moving the wand",
                    style: GoogleFonts.aBeeZee(fontSize: 16),
                    textAlign: TextAlign.center,
                  ),
                  const SizedBox(height: 8),
                  Text(
                    "Calibration will start automatically",
                    style: GoogleFonts.aBeeZee(fontSize: 13, color: Colors.grey),
                    textAlign: TextAlign.center,
                  ),
                  const SizedBox(height: 24),
                  TextButton(
                    onPressed: () => setState(() => _awaitingDeviceWake = false),
                    child: const Text("Cancel", style: TextStyle(color: Colors.red)),
                  ),
                ],
              ),
            )
          : loaded
      ? (calibrating
      ? RefreshIndicator(
        onRefresh: initAll,
        child: SingleChildScrollView(
          physics: const AlwaysScrollableScrollPhysics(),
          child: SizedBox(
            height: MediaQuery.of(context).size.height * 0.8,
            child: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Container(
                    padding: EdgeInsets.all(20),
                    child: Text(
                      calibrationStage == 0
                        ? "Preparing device for calibration..."
                        : calibrationStage == 1
                          ? "Tilt the blinds ALL THE WAY UP"
                          : "Tilt the blinds ALL THE WAY DOWN",
                      style: GoogleFonts.aBeeZee(
                        fontSize: 20,
                        fontWeight: FontWeight.bold
                      ),
                      textAlign: TextAlign.center,
                    ),
                  ),
                  if (calibrationStage == 0)
                    CircularProgressIndicator(
                      color: Theme.of(context).primaryColorLight,
                    ),
                  SizedBox(height: 20),
                  if (calibrationStage == 1 || calibrationStage == 2)
                    Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        ElevatedButton(
                          onPressed: calibrationStage == 1 ? completeStage1 : completeStage2,
                          style: ElevatedButton.styleFrom(
                            backgroundColor: Colors.green,
                            foregroundColor: Colors.white,
                            padding: EdgeInsets.symmetric(horizontal: 30, vertical: 15),
                          ),
                          child: const Text(
                            "Complete",
                            style: TextStyle(fontSize: 16),
                          )
                        ),
                        SizedBox(width: 20),
                        ElevatedButton(
                          onPressed: cancelCalib,
                          style: ElevatedButton.styleFrom(
                            backgroundColor: Colors.red,
                            foregroundColor: Colors.white,
                            padding: EdgeInsets.symmetric(horizontal: 30, vertical: 15),
                          ),
                          child: const Text(
                            "Cancel",
                            style: TextStyle(fontSize: 16),
                          )
                        ),
                      ],
                    )
                  else
                    ElevatedButton(
                      onPressed: cancelCalib,
                      child: const Text(
                        "Cancel",
                        style: TextStyle(
                          color: Colors.red
                        ),
                      )
                    )
                ]
              )
            )
          )
        )
      )
      : (calibrated
      ? Column(
        children: [
          BlindControlWidget(
            imagePath: imagePath,
            blindPosition: _blindPosition,
            onPositionChanged: (value) {
              setState(() {
                _blindPosition = value;
                _movementPending = true;
              });
              updateBlindPosition();
            },
          ),
          Container(
            padding: EdgeInsets.all(25),
            child: Text(
              lastSetMessage
            ),
          ),
          Container(
            padding: EdgeInsets.all(10),
            child: ElevatedButton(
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => SchedulesScreen(peripheralId: widget.peripheralId, periphName: peripheralName,
                    deviceId: widget.deviceId, peripheralNum: widget.peripheralNum, deviceName: widget.deviceName,)
                  )
                );
              },
              child: Text(
                "Set Schedules"
              )
            ),
          )
        ]
      )
      : SizedBox(
        height: MediaQuery.of(context).size.height * 0.8,
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Container(
                padding: EdgeInsets.all(20),
                child: Text(
                  "Peripheral Not Calibrated"
                ),
              ),
              ElevatedButton(
                onPressed: deviceConnected ? calibrate : null,
                style: ElevatedButton.styleFrom(
                  backgroundColor: deviceConnected ? null : Colors.grey,
                ),
                child: const Text("Calibrate")
              )
            ],
          )
        )
      )))
      : BlindmasterProgressIndicator()),
        ],
      ),
      floatingActionButton: Container(
        padding: EdgeInsets.all(25),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            FloatingActionButton(
              heroTag: "rename",
              tooltip: "Rename Peripheral",
              onPressed: rename,
              foregroundColor: Theme.of(context).highlightColor,
              backgroundColor: Theme.of(context).primaryColorDark,
              child: Icon(Icons.drive_file_rename_outline_sharp),
            ),
            FloatingActionButton(
              heroTag: "recalibrate",
              tooltip: "Recalibrate Peripheral",
              onPressed: recalibrate,
              foregroundColor: Theme.of(context).highlightColor,
              backgroundColor: Theme.of(context).primaryColorDark,
              child: Icon(Icons.swap_vert),
            ),
          ],
        ),
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
    );
  }
}