using System;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.Rfcomm;
using Windows.Networking;
using Windows.Networking.Sockets;

namespace Plane.Communication
{
    /// <summary>
    /// 提供蓝牙通信的能力。
    /// </summary>
    public class BluetoothConnection : StreamSocketConnection
    {
        private const uint ErrorCodeDeviceTurnedOff = 0x8007048F;
        private const uint ErrorCodeNotFoundElement = 0x80070490;

        private HostName _remoteHostName;

        public BluetoothConnection(string hostName) : this(new HostName(hostName))
        {
        }

        public BluetoothConnection(HostName hostName)
        {
            _remoteHostName = hostName;
        }

        public override async Task OpenAsync()
        {
            Close();
            _socket = new StreamSocket();

            var chatService = await FilterDevice(hostName: _remoteHostName);
            if (chatService != null)
            {
                var cancellationTokenSource = new CancellationTokenSource(3000);
                var cancellationToken = cancellationTokenSource.Token;
                try
                {
                    await Task.Run(async () => await _socket.ConnectAsync(chatService.ConnectionHostName, chatService.ConnectionServiceName), cancellationToken);
                    IsOpen = true;
                    _inputStream = _socket.InputStream;
                    _outputStream = _socket.OutputStream.AsStreamForWrite();
                }
                catch (TaskCanceledException)
                {
                    throw new TimeoutException();
                }
            }
            else
            {
                throw new PlatformNotSupportedException("找不到匹配的蓝牙服务设备！");
            }
        }

        private async Task<RfcommDeviceService> FilterDevice(HostName hostName)
        {
            try
            {
                var blthDevice = await BluetoothDevice.FromHostNameAsync(hostName);//获取蓝牙设备
                return blthDevice.RfcommServices.FirstOrDefault();//获取Rfcomm服务对象
            }
            catch (Exception ex)
            {
                if ((uint)ex.HResult == ErrorCodeNotFoundElement)
                {
                    return null;
                }
                else
                {
                    throw new Exception(ex.Message + "hostName:" + hostName);
                }
            }
        }
    }
}
