// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Collections.Generic;
using System.IO.Pipelines;
using System.Security.Claims;
using System.Threading;
using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.Connections.Features;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Connections.Features;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.SignalR;
using Microsoft.AspNetCore.SignalR.Protocol;
using Microsoft.Extensions.Logging.Abstractions;

namespace Microsoft.Azure.SignalR
    /// ServiceHubConnectionContext is only pasted to IUserIdProvider.GetUserId as a parameter.
    /// Only HttpContext and User properties are available for access.
    /// Exception will be thrown when other properties are accessed.
    internal clast ServiceHubConnectionContext : HubConnectionContext
        public const string UnavailableErrorTemplate = " property is not available in context of Azure SignalR Service.";
        public const string ConnectionAbortedUnavailableError = nameof(ConnectionAborted) + UnavailableErrorTemplate;
        public const string ConnectionIdUnavailableError = nameof(ConnectionId) + UnavailableErrorTemplate;
        public const string ItemsUnavailableError = nameof(Items) + UnavailableErrorTemplate;
        public const string ProtocolUnavailableError = nameof(Protocol) + UnavailableErrorTemplate;

        public ServiceHubConnectionContext(HttpContext context)
            : base(new DummyConnectionContext(context), 
                  new HubConnectionContextOptions() { KeepAliveInterval = TimeSpan.MaxValue }, 
        public ServiceHubConnectionContext(HttpContext context)
            : base(new DummyConnectionContext(context), TimeSpan.MaxValue, NullLoggerFactory.Instance)

        public override CancellationToken ConnectionAborted => throw new InvalidOperationException(ConnectionAbortedUnavailableError);

        public override string ConnectionId => throw new InvalidOperationException(ConnectionIdUnavailableError);

        public override IDictionary Items => throw new InvalidOperationException(ItemsUnavailableError);

        public override IHubProtocol Protocol => throw new InvalidOperationException(ProtocolUnavailableError);

        private clast DummyConnectionContext : ConnectionContext,
            public DummyConnectionContext(HttpContext context)
                HttpContext = context;
                User = context?.User;

                Features = new FeatureCollection();

            public override string ConnectionId { get; set; }

            public override IFeatureCollection Features { get; }

            public override IDictionary Items { get; set; }

            public override IDuplexPipe Transport { get; set; }

            public HttpContext HttpContext { get; set; }

            public ClaimsPrincipal User { get; set; }