<commit_before>using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Threading;
using System.Threading.Tasks;
using Android.App;
using Android.Bluetooth;
using Android.OS;
using Plugin.BluetoothLE.Internals;


namespace Plugin.BluetoothLE
{
    public class Device : AbstractDevice
    {
        readonly BluetoothManager manager;
        readonly TaskScheduler scheduler;
        readonly Subject<ConnectionStatus> connSubject;
        readonly GattContext context;


        public Device(BluetoothManager manager,
                      BluetoothDevice native,
                      GattCallbacks callbacks,
                      TaskScheduler scheduler) : base(native.Name, ToDeviceId(native.Address))
        {
            this.context = new GattContext(native, callbacks);

            this.manager = manager;
            this.scheduler = scheduler; // this is the thread that the device was scanned on (required by some devices)
            this.connSubject = new Subject<ConnectionStatus>();
        }


        public override object NativeDevice => this.context.NativeDevice;
        public override DeviceFeatures Features => DeviceFeatures.All;


        public override ConnectionStatus Status
        {
            get
            {
                var state = this.manager.GetConnectionState(this.context.NativeDevice, ProfileType.Gatt);
                switch (state)
                {
                    case ProfileState.Connected:
                        return ConnectionStatus.Connected;

                    case ProfileState.Connecting:
                        return ConnectionStatus.Connecting;

                    case ProfileState.Disconnecting:
                        return ConnectionStatus.Disconnecting;

                    case ProfileState.Disconnected:
                    default:
                        return ConnectionStatus.Disconnected;
                }
            }
        }


        public override IObservable<object> Connect(GattConnectionConfig config)
        {
            config = config ?? GattConnectionConfig.DefaultConfiguration;
            this.SetupAutoReconnect(config);

            return Observable.Create<object>(ob =>
            {
                var cancelSrc = new CancellationTokenSource();
                var connected = this
                    .WhenStatusChanged()
                    .Where(x => x == ConnectionStatus.Connected)
                    .Subscribe(_ => ob.Respond(null));

                if (this.Status != ConnectionStatus.Connecting)
                {
                    try
                    {
                        ob.OnNext(ConnectionStatus.Connecting);

                        switch (AndroidConfig.ConnectionThread)
                        {
                            case ConnectionThread.MainThread:
                                Application.SynchronizationContext.Post(_ => this.context.Connect(config), null);
                                break;

                            case ConnectionThread.ScanThread:
                                Task.Factory.StartNew(
                                    () => this.context.Connect(config),
                                    cancelSrc.Token,
                                    TaskCreationOptions.None,
                                    this.scheduler
                                );
                                break;

                            case ConnectionThread.Default:
                            default:
                                this.context.Connect(config);
                                break;
                        }
                    }
                    catch (Exception ex)
                    {
                        ob.OnNext(ConnectionStatus.Disconnected);
                        ob.OnError(ex);
                    }
                }
                return () =>
                {
                    connected?.Dispose();
                    cancelSrc.Dispose();
                };
            });
        }


        public override IObservable<IGattService> GetKnownService(Guid serviceUuid)
            => Observable.Create<IGattService>(ob =>
            {
                var ns = this.context.Gatt.GetService(serviceUuid.ToUuid());
                var service = new GattService(this, this.context, ns);
                ob.Respond(service);
                return Disposable.Empty;
            });


        public override void CancelConnection()
        {
            base.CancelConnection();<commit_msg>when connected get known service<commit_after>using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Threading;
using System.Threading.Tasks;
using Android.App;
using Android.Bluetooth;
using Android.OS;
using Plugin.BluetoothLE.Internals;


namespace Plugin.BluetoothLE
{
    public class Device : AbstractDevice
    {
        readonly BluetoothManager manager;
        readonly TaskScheduler scheduler;
        readonly Subject<ConnectionStatus> connSubject;
        readonly GattContext context;


        public Device(BluetoothManager manager,
                      BluetoothDevice native,
                      GattCallbacks callbacks,
                      TaskScheduler scheduler) : base(native.Name, ToDeviceId(native.Address))
        {
            this.context = new GattContext(native, callbacks);

            this.manager = manager;
            this.scheduler = scheduler; // this is the thread that the device was scanned on (required by some devices)
            this.connSubject = new Subject<ConnectionStatus>();
        }


        public override object NativeDevice => this.context.NativeDevice;
        public override DeviceFeatures Features => DeviceFeatures.All;


        public override ConnectionStatus Status
        {
            get
            {
                var state = this.manager.GetConnectionState(this.context.NativeDevice, ProfileType.Gatt);
                switch (state)
                {
                    case ProfileState.Connected:
                        return ConnectionStatus.Connected;

                    case ProfileState.Connecting:
                        return ConnectionStatus.Connecting;

                    case ProfileState.Disconnecting:
                        return ConnectionStatus.Disconnecting;

                    case ProfileState.Disconnected:
                    default:
                        return ConnectionStatus.Disconnected;
                }
            }
        }


        public override IObservable<object> Connect(GattConnectionConfig config)
        {
            config = config ?? GattConnectionConfig.DefaultConfiguration;
            this.SetupAutoReconnect(config);

            return Observable.Create<object>(ob =>
            {
                var cancelSrc = new CancellationTokenSource();
                var connected = this
                    .WhenStatusChanged()
                    .Where(x => x == ConnectionStatus.Connected)
                    .Subscribe(_ => ob.Respond(null));

                if (this.Status != ConnectionStatus.Connecting)
                {
                    try
                    {
                        ob.OnNext(ConnectionStatus.Connecting);

                        switch (AndroidConfig.ConnectionThread)
                        {
                            case ConnectionThread.MainThread:
                                Application.SynchronizationContext.Post(_ => this.context.Connect(config), null);
                                break;

                            case ConnectionThread.ScanThread:
                                Task.Factory.StartNew(
                                    () => this.context.Connect(config),
                                    cancelSrc.Token,
                                    TaskCreationOptions.None,
                                    this.scheduler
                                );
                                break;

                            case ConnectionThread.Default:
                            default:
                                this.context.Connect(config);
                                break;
                        }
                    }
                    catch (Exception ex)
                    {
                        ob.OnNext(ConnectionStatus.Disconnected);
                        ob.OnError(ex);
                    }
                }
                return () =>
                {
                    connected?.Dispose();
                    cancelSrc.Dispose();
                };
            });
        }


        public override IObservable<IGattService> GetKnownService(Guid serviceUuid) => this
            .WhenStatusChanged()
            .Where(x => x == ConnectionStatus.Connected)
            .Select(_ =>
            {
                var ns = this.context.Gatt.GetService(serviceUuid.ToUuid());
                var service = new GattService(this, this.context, ns);
                return service;
            });


        public override void CancelConnection()
        {
            base.CancelConnection();
{'fraction_non_alphanumeric': 0.06793099753562627, 'fraction_numerical': 0.0, 'mean_word_length': 1.248073217726397, 'pattern_counts': {'":': 0, '<': 14, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2997993', 'n_tokens_mistral': 2034, 'n_tokens_neox': 1874, 'n_words': 401}