using System;
using System.IO;
using System.Threading.Tasks;
using Windows.Devices.Enumeration;
using Windows.Devices.SerialCommunication;

namespace Plane.Communication
{
    /// <summary>
    /// 提供串口通信的能力。
    /// </summary>
    public class SerialPortConnection : StreamConnection
    {
        private uint _baudRate;
        private SerialDevice _device;
        private string _deviceId;

        public SerialPortConnection(string deviceId, uint baudRate = 115200)
        {
            _deviceId = deviceId;
            _baudRate = baudRate;
        }

        public override void Close()
        {
            base.Close();
            _device?.Dispose();
        }

        public override async Task OpenAsync()
        {
            _device = await SerialDevice.FromIdAsync(_deviceId);
            if (_device != null)
            {
                _device.BaudRate = _baudRate;
                _device.DataBits = 8;
                _device.StopBits = SerialStopBitCount.One;
                _device.Parity = SerialParity.None;
                _device.IsDataTerminalReadyEnabled = true;
                _device.IsRequestToSendEnabled = true;
                _device.ReadTimeout = TimeSpan.FromMilliseconds(1200);

                _inputStream = _device.InputStream;
                _outputStream = _device.OutputStream.AsStreamForWrite();

                IsOpen = true;
            }
            else
            {
                var deviceAccessStatus = DeviceAccessInformation.CreateFromId(_deviceId).CurrentStatus;
                string message;
                if (deviceAccessStatus == DeviceAccessStatus.DeniedByUser)
                {
                    message = "Access to the device was blocked by the user : " + _deviceId;
                }
                else if (deviceAccessStatus == DeviceAccessStatus.DeniedBySystem)
                {
                    // This status is most likely caused by app permissions (did not declare the device in the app's package.appxmanifest)
                    // This status does not cover the case where the device is already opened by another app.
                    message = "Access to the device was blocked by the system : " + _deviceId;
                }
                else
                {
                    // Most likely the device is opened by another app, but cannot be sure
                    message = "Unknown error, possibly opened by another app : " + _deviceId;
                }
                throw new DeviceAccessDeniedException(message, deviceAccessStatus);
            }
        }
    }
}