import 'dart:async';
import 'dart:math';
import 'dart:typed_data';

import 'package:fengshui_compass/components/cross_paint.dart';
import 'package:fengshui_compass/components/my_icon.dart';
import 'package:fengshui_compass/pages/login_page.dart';
import 'package:fengshui_compass/states/region.dart';
import 'package:flutter/material.dart';
import 'package:flutter_serial_port_api/flutter_serial_port_api.dart';
import 'package:provider/provider.dart';
import 'package:stream_transform/stream_transform.dart';

import '../components/region_selector.dart';
import '../utils/recv_parse.dart';

class CompassPage extends StatefulWidget {
  const CompassPage({Key key}) : super(key: key);

  @override
  State<StatefulWidget> createState() => _CompassState();
}

class _CompassState extends State<CompassPage> {
  // 串口相关
  bool isPortOpened = false;
  SerialPort _serialPort;
  StreamSubscription _subscription;

  // 传感器状态
  bool isLock = true;
  bool isUpClose = true;
  bool isSideClose = true;

  double w_x = 0.5;
  double w_y = 0.5;

  // 与磁北极夹角
  double myaw = 0.0;

  String distance = "";

  var lista = [];
  var listb = [];
  var listc = [];

  void initDevice() {}

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

  Future<void> initPort() async {
    // 20ms接收一次串口数据，防抖，定义接收缓存
    final debounceTransformer = StreamTransformer<Uint8List, dynamic>.fromBind(
        (s) => s.transform(debounceBuffer(const Duration(milliseconds: 20))));

    if (!isPortOpened) {
      Device theDevice = Device("/dev/ttyS2", "/dev/ttyS2");
      var serialPort = await FlutterSerialPortApi.createSerialPort(
          theDevice, 115200,
          parity: 0, dataBits: 8, stopBit: 1);

      bool openResult = await serialPort.open();
      setState(() {
        _serialPort = serialPort;
        isPortOpened = openResult;
      });
      await openRange();

      _subscription = _serialPort.receiveStream
          .transform(debounceTransformer)
          .listen((recv) {
        // recvData - 9E01040100000000000000065E
        String recvData = formatReceivedData(recv);
        print("Receive format: $recvData");
        parsingRecvCom(recvData);
        // 解析收到的结果，得到陀螺、地磁、测距结果
      });

      await openCompass();
    }
  }

  Future<void> closePort() async {
    bool closeResult = await _serialPort.close();
    setState(() {
      isPortOpened = !closeResult;
    });
  }

  Future<void> openCompass() async {
    print("compass open");
    _serialPort
        .write(Uint8List.fromList(hexToUnits("7E01020100000000000000010D0A")));
  }

  Future<void> closeCompass() async {
    print("compass close");
    _serialPort
        .write(Uint8List.fromList(hexToUnits("7E01020000000000000000010D0A")));
  }

  Future<void> openSideLaser() async {
    print("side open");
    _serialPort
        .write(Uint8List.fromList(hexToUnits("7E01010100000000000000010D0A")));
  }

  Future<void> closeSideLaser() async {
    print("side close");
    _serialPort
        .write(Uint8List.fromList(hexToUnits("7E01010000000000000000010D0A")));
  }

  Future<void> openUpLaser() async {
    _serialPort
        .write(Uint8List.fromList(hexToUnits("7e01010300000000000000010d0a")));
  }

  Future<void> closeUpLaser() async {
    _serialPort
        .write(Uint8List.fromList(hexToUnits("7e01010200000000000000010d0a")));
  }

  Future<void> openRange() async {
    _serialPort
        .write(Uint8List.fromList(hexToUnits("7e01040100000000000000010d0a")));
  }

  Future<void> raging() async {
    if (!isLock) {
      switchCompass();
    }
    _serialPort
        .write(Uint8List.fromList(hexToUnits("7e01040200000000000000010d0a")));
  }

  Future<void> switchCompass() async {
    if (isLock) {
      await openCompass();
    } else {
      await closeCompass();
      setState(() {
        w_x = 0.5;
        w_y = 0.5;
      });
    }
    setState(() {
      isLock = !isLock;
    });
  }

  loginAction() {
    Navigator.push(
        context, MaterialPageRoute(builder: (context) => LoginPage()));
  }

  parsingRecvCom(str) {
    if (str.contains("9E010201") &&
        (str.length > (str.indexOf("9E010201") + 50))) {
      var roll_l = hexToInt(str.substring(8, 10));
      var roll_h = hexToInt(str.substring(10, 12));
      var pitch_l = hexToInt(str.substring(12, 14));
      var pitch_h = hexToInt(str.substring(14, 16));
      // var yaw_l = hexToInt(str.substring(16, 18));
      // var yaw_h = hexToInt(str.substring(18, 20));

      var pos = str.indexOf("9E010301");
      // var mx_h = hexToInt(str.substring(pos+8, pos+10));
      // var mx_l = hexToInt(str.substring(pos+10, pos+12));
      // var my_h = hexToInt(str.substring(pos+12, pos+14));

      var myaw_flag = hexToInt(str.substring(pos + 14, pos + 16));
      var myaw_h = hexToInt(str.substring(pos + 16, pos + 18));
      var myaw_l = hexToInt(str.substring(pos + 18, pos + 20));

      var roll_tmp = (roll_h * 256 + roll_l) * 180 / 32768;
      var pitch_tmp = (pitch_h * 256 + pitch_l) * 180 / 32768;
      // var yaw = (yaw_h * 256 + yaw_l)  * 180 /32768;

      // -180~180
      var ff = myaw_flag == 1 ? -1 : 1;
      var temp_myaw = (myaw_h * 256 + myaw_l) * 0.01 * ff + 180;

      if (roll_tmp > 180) roll_tmp = roll_tmp - 360;
      if (pitch_tmp > 180) pitch_tmp = pitch_tmp - 360;

      var w_x_tmp = 0.0;
      var w_y_tmp = 0.0;

      // 倾角<30度
      var w_total = sqrt(
          roll_tmp.abs() * roll_tmp.abs() + pitch_tmp.abs() * pitch_tmp.abs());

      if (w_total <= 30) {
        w_y_tmp = 0.5 - 0.07 * roll_tmp / 30.0;
        w_x_tmp = 0.5 - 0.07 * pitch_tmp / 30.0;
      } else if (w_total > 30) {
        //todo
        w_y_tmp = 0.5 - 0.07 * w_total / 30.0;
        w_x_tmp = 0.5 - 0.07 * w_total / 30.0;
      }

      // todo 其他情况

      var meanValue;

      if (lista.length < 20) {
        lista.add(temp_myaw);
        meanValue = null;
      } else {
        lista.removeAt(0);
        lista.add(temp_myaw);
        meanValue = lista.map((e) => e).reduce((a, b) => a + b) / lista.length;
      }

      setState(() {
        // print("roll: $roll_tmp pitch: $pitch_tmp");
        // print("w_x: $w_x_tmp, w_y: $w_y_tmp");
        // if (meanValue != null) {
        //   myaw = meanValue;
        // } else {
        //   myaw = 0;
        // }
        myaw = temp_myaw;

        w_x = w_x_tmp;
        w_y = w_y_tmp;

        // 水平仪 0.5+-0.07范围
        // x旋转y在动 y旋转x在动 roll改变y坐标，pitch改变x坐标
      });
    } else if (str.contains("9E010401") &&
        (str.length >= ((str.indexOf("9E010401") + 26)))) {
      var pos = str.indexOf("9E010401");
      int rh = hexToInt(str.substring(pos + 16, pos + 18));
      int rl = hexToInt(str.substring(pos + 18, pos + 20));
      int result = rh * 256 + rl;
      print("测距$result");

      setState(() {
        distance = (result.toDouble() / 1000).toStringAsFixed(2);
      });
    } else {}
  }

  // 拼接城市
  String spliceCityName(String pname, String cname) {
    if (pname == '') return '未选择城市';
    StringBuffer sb = StringBuffer();
    sb.write(pname);
    if (cname == '') return sb.toString();
    sb.write(' - ');
    sb.write(cname);
    return sb.toString();
  }

  // bool strEmpty(String? value) {
  //   if (value == null) return true;
  //   return value.trim().isEmpty;
  // }

  selectRegion() {
    showDialog(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
            title: Text('选择城市校准磁偏角'),
            content: RegionSelector(),
            actions: <Widget>[
              TextButton(
                  onPressed: () {
                    Navigator.pop(context);
                  },
                  child: const Text('关闭')),
              TextButton(
                  onPressed: () {
                    Provider.of<RegionProvider>(context, listen: false)
                        .saveRegion();
                    Navigator.pop(context);
                  },
                  child: const Text('保存'))
            ],
          );
        }).then((value) {
      Provider.of<RegionProvider>(context, listen: false).resetTemp();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: const BoxDecoration(
          image: DecorationImage(
              image: AssetImage("assets/images/bg.png"), fit: BoxFit.cover)),
      child: Scaffold(
        backgroundColor: Colors.transparent,
        appBar: AppBar(
          backgroundColor: Colors.transparent,
          elevation: 0,
          centerTitle: true,
          title: const Text(
            '定盘星',
            style: TextStyle(color: Colors.white),
          ),
          leading: IconButton(
            color: Colors.amber,
            icon: Icon(isLock ? MyIcons.icon_mima : MyIcons.icon_jiesuo),
            onPressed: switchCompass,
          ),
          actions: [
            //todo
            // 更改背景图
            IconButton(
              color: Colors.amber,
              icon: const Icon(
                Icons.person,
                size: 22,
              ),
              onPressed: loginAction,
            ),
          ],
        ),
        body: SafeArea(
            child: ConstrainedBox(
          constraints: const BoxConstraints(minHeight: 600),
          child: Stack(
            alignment: Alignment.center,
            children: [
              // 罗盘
              Column(
                children: [
                  const Padding(padding: EdgeInsets.only(top: 145)),
                  Row(
                    children: [
                      Spacer(flex: 1),
                      Container(
                        width: 700,
                        height: 700,
                        child: Stack(
                          children: [
                            Transform.rotate(
                              angle: myaw * pi / 360,
                              child: const Image(
                                  image:
                                      AssetImage("assets/images/compass.png"),
                                  fit: BoxFit.fill),
                            ),
                            Align(
                              alignment: FractionalOffset(w_x, w_y),
                              child: const Image(
                                image: AssetImage("assets/images/water.png"),
                              ),
                            ),
                            CrossPaint(),
                          ],
                        ),
                      ),
                      const Spacer(flex: 1),
                    ],
                  )
                ],
              ),
              // 最上面一行, lock azimuth login
              Positioned(
                  top: 5,
                  child: Column(
                    children: [
                      const Image(
                        width: 15,
                        height: 15,
                        image: AssetImage("assets/images/arrow.png"),
                        fit: BoxFit.contain,
                      ),
                      Text(
                        // "${azimuth.toStringAsFixed(2)}",
                        myaw.toStringAsFixed(2),
                        style:
                            const TextStyle(color: Colors.amber, fontSize: 36),
                      ),
                    ],
                  )),
              Positioned(
                  top: 5,
                  right: 8,
                  child: IconButton(
                    onPressed: () => selectRegion(),
                    icon: const Icon(Icons.settings, color: Colors.amber),
                  )),
              // 最下面一行，ranging value openlaser
              Positioned(
                  bottom: 80,
                  left: 50,
                  child: IconButton(
                      onPressed: raging,
                      icon: const Icon(
                        MyIcons.icon_celiang,
                        size: 34,
                      ),
                      color: Colors.amber)),
              const Positioned(
                  width: 180,
                  height: 90,
                  bottom: 60,
                  child: Image(
                    image: AssetImage("assets/images/range_input.png"),
                    fit: BoxFit.contain,
                  )),
              Positioned(
                  width: 180,
                  height: 90,
                  bottom: 60,
                  child: Align(
                    alignment: Alignment.centerRight,
                    child: Padding(
                      padding: const EdgeInsets.only(right: 15),
                      child: Text(
                        "${distance} m",
                        style:
                            const TextStyle(color: Colors.amber, fontSize: 28),
                      ),
                    ),
                  )),

              Positioned(
                bottom: 60,
                right: 40,
                height: 120,
                width: 100,
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.center,
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    IconButton(
                        color: Colors.amber,
                        onPressed: () {
                          if (isUpClose) {
                            openUpLaser();
                          } else {
                            closeUpLaser();
                          }
                          setState(() {
                            isUpClose = !isUpClose;
                          });
                        },
                        icon: Icon(
                            isUpClose
                                ? MyIcons.icon_shangdeng
                                : MyIcons.icon_shangdnegguanbi,
                            size: 36)),
                    IconButton(
                        color: Colors.amber,
                        onPressed: () {
                          if (isSideClose) {
                            openSideLaser();
                          } else {
                            closeSideLaser();
                          }
                          setState(() {
                            isSideClose = !isSideClose;
                          });
                        },
                        icon: Icon(
                          isSideClose
                              ? MyIcons.icon_zuoyoudneg
                              : MyIcons.icon_zuoyoudengguanbi,
                          size: 32,
                        ))
                  ],
                ),
              )
            ],
          ),
        )),
      ),
    );
  }
}
