using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using RX_Web_Sample.Models;

namespace RX_Web_Sample
{
    public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton<DevicesService>();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        // Step 1: Add parametr IHost
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHost host)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseWebSockets();

            app.Use(async (context, next) =>
            {
                if (context.Request.Path == "/ws/devices/led" && context.WebSockets.IsWebSocketRequest)
                {
                    var socket = await context.WebSockets.AcceptWebSocketAsync();

                    var trueBuffer = Encoding.UTF8.GetBytes("true");
                    var falseBuffer = Encoding.UTF8.GetBytes("false");

                    void SendResponse(bool value)
                    {
                        socket.SendAsync(value ? trueBuffer : falseBuffer, System.Net.WebSockets.WebSocketMessageType.Text, true, CancellationToken.None).Wait();
                    }

                    using (var scope = host.Services.CreateScope())
                    {
                        var taskCompletionSource = new TaskCompletionSource<bool>();
                        using (var subscription = scope
                        .ServiceProvider
                        .GetService<DevicesService>()
                        .LedObservable
                        .Subscribe(
                            SendResponse,
                            ex => taskCompletionSource.SetException(ex),
                            () => taskCompletionSource.SetResult(true)))
                        {
                            await taskCompletionSource.Task;
                        }
                    }

                    await socket.CloseAsync(System.Net.WebSockets.WebSocketCloseStatus.NormalClosure, "End of stream", CancellationToken.None);
                }

            });
        }
    }
}
