﻿#region Copyright notice and license
// Copyright 2015 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Grpc.Core;
using Grpc.Core.Utils;
using Grpc.Reflection.V1Alpha;
using Google.Protobuf.Reflection;

namespace Grpc.Reflection
{
    /// <summary>
    /// Implementation of server reflection service.
    /// </summary>
    public class ReflectionServiceImpl : Grpc.Reflection.V1Alpha.ServerReflection.ServerReflectionBase
    {
        readonly List<string> services;
        readonly SymbolRegistry symbolRegistry;

        /// <summary>
        /// Creates a new instance of <c>ReflectionServiceIml</c>.
        /// </summary>
        public ReflectionServiceImpl(IEnumerable<string> services, SymbolRegistry symbolRegistry)
        {
            this.services = new List<string>(services);
            this.symbolRegistry = symbolRegistry;
        }

        /// <summary>
        /// Creates a new instance of <c>ReflectionServiceIml</c>.
        /// </summary>
        public ReflectionServiceImpl(IEnumerable<ServiceDescriptor> serviceDescriptors)
        {
            this.services = new List<string>(serviceDescriptors.Select((serviceDescriptor) => serviceDescriptor.FullName));
            this.symbolRegistry = SymbolRegistry.FromFiles(serviceDescriptors.Select((serviceDescriptor) => serviceDescriptor.File));
        }

        /// <summary>
        /// Creates a new instance of <c>ReflectionServiceIml</c>.
        /// </summary>
        public ReflectionServiceImpl(params ServiceDescriptor[] serviceDescriptors) : this((IEnumerable<ServiceDescriptor>) serviceDescriptors)
        {
        }

        /// <summary>
        /// Processes a stream of server reflection requests.
        /// </summary>
        public override async Task ServerReflectionInfo(IAsyncStreamReader<ServerReflectionRequest> requestStream, IServerStreamWriter<ServerReflectionResponse> responseStream, ServerCallContext context)
        {
            while (await requestStream.MoveNext())
            {
                var response = ProcessRequest(requestStream.Current);
                await responseStream.WriteAsync(response);
            }
        }

        ServerReflectionResponse ProcessRequest(ServerReflectionRequest request)
        {
            switch (request.MessageRequestCase)
            {
                case ServerReflectionRequest.MessageRequestOneofCase.FileByFilename:
                    return FileByFilename(request.FileByFilename);
                case ServerReflectionRequest.MessageRequestOneofCase.FileContainingSymbol:
                    return FileContainingSymbol(request.FileContainingSymbol);
                case ServerReflectionRequest.MessageRequestOneofCase.ListServices:
                    return ListServices();
                case ServerReflectionRequest.MessageRequestOneofCase.AllExtensionNumbersOfType:
                case ServerReflectionRequest.MessageRequestOneofCase.FileContainingExtension:
                default:
                    return CreateErrorResponse(StatusCode.Unimplemented, "Request type not supported by C# reflection service.");
            }
        }

        ServerReflectionResponse FileByFilename(string filename)
        {
            FileDescriptor file = symbolRegistry.FileByName(filename);
            if (file == null)
            {
                return CreateErrorResponse(StatusCode.NotFound, "File not found.");
            }

            var transitiveDependencies = new HashSet<FileDescriptor>();
            CollectTransitiveDependencies(file, transitiveDependencies);

            return new ServerReflectionResponse
            {
                FileDescriptorResponse = new FileDescriptorResponse { FileDescriptorProto = { transitiveDependencies.Select((d) => d.SerializedData) } }
            };
        }

        ServerReflectionResponse FileContainingSymbol(string symbol)
        {
            FileDescriptor file = symbolRegistry.FileContainingSymbol(symbol);
            if (file == null)
            {
                return CreateErrorResponse(StatusCode.NotFound, "Symbol not found.");
            }

            var transitiveDependencies = new HashSet<FileDescriptor>();
            CollectTransitiveDependencies(file, transitiveDependencies);

            return new ServerReflectionResponse
            {
                FileDescriptorResponse = new FileDescriptorResponse { FileDescriptorProto = { transitiveDependencies.Select((d) => d.SerializedData) } }
            };
        }

        ServerReflectionResponse ListServices()
        {
            var serviceResponses = new ListServiceResponse();
            foreach (string serviceName in services)
            {
                serviceResponses.Service.Add(new ServiceResponse { Name = serviceName });
            }

            return new ServerReflectionResponse
            {
                ListServicesResponse = serviceResponses
            };
        }

        ServerReflectionResponse CreateErrorResponse(StatusCode status, string message)
        {
            return new ServerReflectionResponse
            {
                ErrorResponse = new ErrorResponse { ErrorCode = (int) status, ErrorMessage = message }
            };
        }

        void CollectTransitiveDependencies(FileDescriptor descriptor, HashSet<FileDescriptor> pool)
        {
            pool.Add(descriptor);
            foreach (var dependency in descriptor.Dependencies)
            {
                if (pool.Add(dependency))
                {
                    // descriptors cannot have circular dependencies
                    CollectTransitiveDependencies(dependency, pool);
                }
            }
        }
    }
}
