import 'dart:async';

import 'package:app_settings/app_settings.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bluetooth_serial/flutter_bluetooth_serial.dart';
import 'package:permission_handler/permission_handler.dart';

import '../objects/bluetooth_device_entry.dart';
import '../objects/bluetooth_object.dart';
import '../screens/bluetooth_device_settings.dart';
import '../widgets/custom_list_tile.dart';
import '../widgets/single_section.dart';

class BluetoothScreen extends StatefulWidget {
  final bool start = true;

  const BluetoothScreen({super.key});

  @override
  State<BluetoothScreen> createState() => _BluetoothScreen();
}

// debugPrint("r: ${r.device.name} ${r.device.address} ${r.rssi}");
class _BluetoothScreen extends State<BluetoothScreen> {
  final List<BluetoothObject> _discoveryResults = [];

  late BluetoothObject? _activeObject;

  late Stream<BluetoothDiscoveryResult>? _stream;
  late StreamSubscription<BluetoothDiscoveryResult>? _streamSubscription;

  bool _isDiscovering = false;
  bool _enabledPermissions = false;
  bool _enabledBluetooth = false;

  ButtonStyle buttonStyle = ElevatedButton.styleFrom(
    foregroundColor: Colors.black,
    backgroundColor: const Color(0xFFFDE100), // Text Color (Foreground color)
  );

  bool get _hasActiveObject {
    return _activeObject == null ? false : true;
  }

  @override
  void initState() {
    _enablePermissions();
    _enableBluetooth();
    super.initState();
    _activeObject = null;
    _streamSubscription = null;
    if (widget.start) {
      _startDiscovery();
    }
  }

  @override
  void dispose() {
    // Avoid memory leak (`setState` after dispose) and cancel discovery
    _streamSubscription?.cancel();
    _activeObject?.disconnectDevice();
    super.dispose();
    debugPrint("called dispose");
  }

  Future<void> _enablePermissions() async {
    debugPrint("Test");
    PermissionStatus bluetoothScan = await Permission.bluetoothScan.request();
    PermissionStatus bluetoothConnect = await Permission.bluetoothConnect.request();
    bool granted = bluetoothScan.isGranted && bluetoothConnect.isGranted;
    setState(() {
      _enabledPermissions = granted;
    });
  }

  Future<void> _enableBluetooth() async {
    if (!_enabledPermissions) {
      return;
    }
    bool? enabled = await FlutterBluetoothSerial.instance.requestEnable();
    enabled ??= false;
    setState(() {
      _enabledBluetooth = enabled!;
    });
  }

  Future<void> _startDiscovery() async {
    if (!_enabledPermissions) {
      return;
    }
    setState(() => _isDiscovering = true);
    _stream = FlutterBluetoothSerial.instance.startDiscovery();
    _streamSubscription = _stream!.listen(_discoveryOnListen);
    _streamSubscription!.onDone(_discoveryOnDone);
  }

  Future<void> _discoveryOnDone() async {
    setState(() => _isDiscovering = false);
  }

  Future<void> _cancelDiscovery() async {
    await _streamSubscription?.cancel();
    setState(() => _isDiscovering = false);
  }

  Future<void> _discoveryOnListen(BluetoothDiscoveryResult event) async {
    setState(() {
      final int existingIndex =
          _discoveryResults.indexWhere((element) => element.device.address == event.device.address);
      if (existingIndex >= 0) {
        _discoveryResults[existingIndex] = BluetoothObject(event);
      } else {
        _discoveryResults.add(BluetoothObject(event));
      }
    });
  }

  Future<void> _restartDiscovery() async {
    _discoveryResults.clear();
    if (_hasActiveObject) {
      _discoveryResults.add(_activeObject!);
    }
    if (_streamSubscription != null) {
      await _cancelDiscovery();
    }
    await _startDiscovery();
  }

  Future<void> _toggleConnection(BluetoothObject bluetoothObject) async {
    await _cancelDiscovery();
    if (_hasActiveObject) {
      _activeObject!.disconnectDevice();
      _activeObject = bluetoothObject;
    } else {
      _activeObject = bluetoothObject;
    }
    _activeObject!.isConnected ? await bluetoothObject.disconnectDevice() : await bluetoothObject.connectDevice();
  }

  //stty -F /dev/service 19200 parenb -parodd -cstopb cs8
  //cat /dev/service | xargs -n 1 /home/script/automaticcloud.sh

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: _isDiscovering ? const Text('Bluetooth Devices (searching...)') : const Text('Bluetooth Devices'),
        actions: <Widget>[
          _isDiscovering
              ? FittedBox(
                  child: Container(
                    margin: const EdgeInsets.all(16.0),
                    child: const CircularProgressIndicator(
                      valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
                    ),
                  ),
                )
              : IconButton(
                  icon: const Icon(Icons.replay),
                  onPressed: _restartDiscovery,
                )
        ],
      ),
      body: Center(
        child: ListView(children: [
          SingleChildScrollView(
            physics: const ScrollPhysics(),
            child: Column(
              children: <Widget>[
                SingleSection(
                  title: "Setup",
                  children: [
                    CustomListTile(
                      title: _enabledBluetooth ? "Bluetooth Enabled" : "Please Enable Bluetooth (click me)",
                      icon: _enabledBluetooth ? Icons.check_circle_outline_rounded : Icons.info_outline_rounded,
                      onTap: () async {
                        await _enableBluetooth();
                      },
                    ),
                    CustomListTile(
                      title: _enabledPermissions ? "Permissions Granted" : "Please Grant Permissions (click me)",
                      icon: _enabledPermissions ? Icons.check_circle_outline_rounded : Icons.info_outline_rounded,
                      onTap: () async {
                        await _enablePermissions();
                      },
                    ),
                    CustomListTile(
                      title: "App Settings (if permissions denied)",
                      icon: Icons.settings,
                      onTap: () async {
                        await AppSettings.openAppSettings();
                      },
                    ),
                  ],
                ),
                Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 16.0),
                  child: Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [
                    // const EdgeInsets defaultContentPadding = EdgeInsets.symmetric(horizontal: 16.0);
                    Expanded(
                      child: ElevatedButton(
                        onPressed: () async {
                          /*await Permission.bluetoothConnect.request();
                          await Permission.bluetoothScan.request();
                          if (await Permission.bluetoothScan.request().isGranted) {
                            // Either the permission was already granted before or the user just granted it.
                            debugPrint("Location Permission is granted");
                          } else {
                            debugPrint("Location Permission is denied.");
                          }*/
                        },
                        style: buttonStyle,
                        child: const Text("Get BT Permissions"),
                      ),
                    ),
                    const SizedBox(width: 16.0),
                    Expanded(
                      child: ElevatedButton(
                        onPressed: () async {
                          _restartDiscovery();
                        },
                        style: buttonStyle,
                        child: const Text("Restart Scan"),
                      ),
                    )
                  ]),
                ),
                const Divider(),
                SingleSection(
                  title: "Bluetooth Devices",
                  children: [
                    const CustomListTile(
                      title: "short Press for connect / disconnect",
                      icon: Icons.info_outline_rounded,
                    ),
                    const CustomListTile(
                      title: "long press for pair / unpair",
                      icon: Icons.info_outline_rounded,
                    ),
                    const Divider(),
                    ListView.builder(
                      physics: const NeverScrollableScrollPhysics(),
                      shrinkWrap: true,
                      itemCount: _discoveryResults.length,
                      itemBuilder: (BuildContext context, index) {
                        BluetoothObject bluetoothObject = _discoveryResults[index];
                        final device = bluetoothObject.device;
                        return BluetoothDeviceEntry(
                          settingsPage: BluetoothDeviceSettings(bluetoothObject: bluetoothObject),
                          context: context,
                          device: device,
                          bluetoothObject: bluetoothObject,
                          onTap: () async {
                            await _toggleConnection(bluetoothObject);
                          },
                          onLongPress: () async {
                            await bluetoothObject.bondDevice();
                          },
                        );
                      },
                    ),
                  ],
                )
              ],
            ),
          ),
        ]),
      ),
      //drawer: const Sidebar(),
    );
  }
}
