import 'dart:async';
import 'dart:ffi';
import 'dart:typed_data';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_bluetooth_serial/flutter_bluetooth_serial.dart';
import 'bluetooth.dart';

class ConnectionPage extends StatefulWidget {
  final DeviceSelectionWrapper currentState;
  const ConnectionPage({super.key, required this.currentState});

  @override
  State<ConnectionPage> createState() => _ConnectionPage();
}

List<BluetoothDiscoveryResult> scanBluetoothDevice(
    List<BluetoothDiscoveryResult> results) {
  print("Scanning started!");
  FlutterBluetoothSerial.instance.startDiscovery().listen((r) {
    print(r.device.address);
    final existingIndex = results
        .indexWhere((element) => element.device.address == r.device.address);
    if (existingIndex >= 0)
      results[existingIndex] = r;
    else
      results.add(r);
  });

  return results;
}

Widget generateDiscoveredBluetoothList(
    List<BluetoothDevice> bondedDevices, Function callback) {
  List<Widget> devs = [];
  for (int i = 0; i < bondedDevices.length; i++) {
    BluetoothDevice thisDevice = bondedDevices[i];
    devs.add(Container(
        margin: EdgeInsetsDirectional.all(4),
        color: Colors.white,
        child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [
          Container(
              alignment: Alignment.center,
              padding: EdgeInsetsDirectional.all(14),
              child: Image.asset('assets/images/bt.png')),
          Container(
              alignment: Alignment.center,
              padding: EdgeInsetsDirectional.all(14),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text(
                    thisDevice.address,
                    textAlign: TextAlign.left,
                  ),
                  Text(
                    thisDevice.name!,
                    textAlign: TextAlign.left,
                  )
                ],
              )),
          Container(
              alignment: Alignment.center,
              padding: EdgeInsetsDirectional.all(14),
              child: ElevatedButton(
                style: ElevatedButton.styleFrom(),
                onPressed: () {
                  callback(thisDevice.address, thisDevice.name!);
                },
                child: const Text('選擇'),
              ))
        ])));
  }
  return Container(
      height: 400,
      padding: EdgeInsetsDirectional.all(4),
      decoration: BoxDecoration(
          border: Border.all(
            color: Color.fromARGB(255, 226, 226, 226),
          ),
          borderRadius: BorderRadius.all(Radius.circular(4))),
      child: SingleChildScrollView(
          child: Column(
        children: devs,
      )));
}

class _ConnectionPage extends State<ConnectionPage> {
  //Bluetooth Connection Related
  List<BluetoothDevice> bondedDevices = <BluetoothDevice>[];
  DeviceSelectionWrapper operatingDevice = DeviceSelectionWrapper();
  String _statusText = "請選擇並連接到一個 Bluetooth Serial 裝置";

  @override
  Widget build(BuildContext context) {
    operatingDevice = widget.currentState;
    //Check if it is connected
    if (operatingDevice.deviceConnected) {
      setState(() {
        _statusText = "已連接到裝置 " +
            operatingDevice.deviceName +
            " (" +
            operatingDevice.deviceAddr +
            ")";
      });
    }
    //Load all the bluetooth device on screen load
    FlutterBluetoothSerial.instance
        .getBondedDevices()
        .then((List<BluetoothDevice> deviceLists) {
      setState(() {
        bondedDevices = deviceLists;
      });
    });
    return Scaffold(
      appBar: null,
      body: Column(
        children: [
          //Title banner
          Image.asset('assets/images/scanner.png'),
          //Control Buttons
          Container(
              alignment: Alignment.topLeft,
              padding: EdgeInsetsDirectional.all(16),
              child: Row(
                children: [
                  //List Bluetooth Device Button
                  Container(
                      padding: EdgeInsets.symmetric(horizontal: 2),
                      child: ElevatedButton(
                        onPressed: () {
                          FlutterBluetoothSerial.instance
                              .getBondedDevices()
                              .then((List<BluetoothDevice> deviceLists) {
                            _statusText = "";
                            for (var device in deviceLists) {
                              print(device.address + " / " + device.name!);
                              setState(() {
                                _statusText =
                                    "已更新藍牙裝置列表。如仍無法找到目標模組，請先到藍牙設定嘗試連接一次再載入列表。";
                              });
                            }

                            setState(() {
                              bondedDevices = deviceLists;
                            });
                          });
                        },
                        child: const Text('重新載入列表'),
                      )),
                  Container(
                      padding: EdgeInsets.symmetric(horizontal: 2),
                      child:
                          //Connect Device Button
                          ElevatedButton(
                        style: ElevatedButton.styleFrom(
                            backgroundColor: (operatingDevice.deviceSelected &&
                                    !operatingDevice.deviceConnected)
                                ? Colors.green
                                : Color.fromARGB(255, 192, 192, 192)),
                        onPressed: () async {
                          if (operatingDevice.deviceSelected &&
                              !operatingDevice.deviceConnected) {
                            setState(() {
                              _statusText = "正在建立連接…";
                            });
                            //Not connected yet. Establish connection
                            try {
                              operatingDevice.connection =
                                  await BluetoothConnection.toAddress(
                                      operatingDevice.deviceAddr);
                              print('Connected to the device');
                              setState(() {
                                _statusText = "已連接到 " +
                                    operatingDevice.deviceName +
                                    " (" +
                                    operatingDevice.deviceAddr +
                                    ")";
                              });
                              operatingDevice.deviceConnected = true;
                              operatingDevice.connection.input!
                                  .listen((Uint8List data) {
                                print(data);
                              });
                            } catch (ex) {
                              print(ex);
                              setState(() {
                                _statusText = "無法連接到選定的裝置 （查看偵錯主控台以了解更多）";
                              });
                            }
                          } else {
                            if (!operatingDevice.deviceSelected) {
                              setState(() {
                                _statusText = "沒有已選擇之藍牙裝置";
                              });
                            } else if (operatingDevice.connection.isConnected) {
                              setState(() {
                                _statusText = "藍牙裝置已連接";
                              });
                            }
                          }
                        },
                        child: const Text('連接'),
                      )),

                  Container(
                      padding: EdgeInsets.symmetric(horizontal: 2),
                      child: ElevatedButton(
                        style: ElevatedButton.styleFrom(
                            backgroundColor: (operatingDevice.deviceSelected &&
                                    operatingDevice.deviceConnected)
                                ? Colors.red
                                : Color.fromARGB(255, 192, 192, 192)),
                        onPressed: () {
                          //Disconnect BT devices
                          if (operatingDevice.deviceConnected &&
                              operatingDevice.deviceConnected) {
                            operatingDevice.connection.close();
                            print('Connection Closed');
                            setState(() {
                              _statusText = "已中斷連接";
                            });
                            operatingDevice.deviceConnected = false;
                          }
                        },
                        child: const Text('斷開'),
                      ))
                ],
              )),
          Container(
            padding: const EdgeInsetsDirectional.all(16),
            child: Text(
                //Show the latest found Bluetooth addr
                _statusText),
          ),
          Container(
              padding: const EdgeInsetsDirectional.all(16),
              child: generateDiscoveredBluetoothList(bondedDevices,
                  (String addr, String name) {
                setState(() {
                  operatingDevice.deviceAddr = addr;
                  operatingDevice.deviceName = name;
                  operatingDevice.deviceSelected = true;
                  _statusText = "已選擇裝置 " + name + "(" + addr + ")";
                });
                print("已選擇裝置 " + name + "(" + addr + ")");
              })),

          Center(
            child: ElevatedButton(
              onPressed: () {
                Navigator.pop(context, operatingDevice);
              },
              child: const Text('返回'),
            ),
          )
        ],
      ),
    );
  }
}
