#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.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core.Internal;
using Grpc.Core.Utils;

namespace Grpc.Core
{
    /// <summary>
    /// Channel option specified when creating a channel.
    /// Corresponds to grpc_channel_args from grpc/grpc.h.
    /// </summary>
    public sealed class ChannelOption
    {
        /// <summary>
        /// Type of <c>ChannelOption</c>.
        /// </summary>
        public enum OptionType
        {
            /// <summary>
            /// Channel option with integer value.
            /// </summary>
            Integer,
            
            /// <summary>
            /// Channel option with string value.
            /// </summary>
            String
        }

        private readonly OptionType type;
        private readonly string name;
        private readonly int intValue;
        private readonly string stringValue;

        /// <summary>
        /// Creates a channel option with a string value.
        /// </summary>
        /// <param name="name">Name.</param>
        /// <param name="stringValue">String value.</param>
        public ChannelOption(string name, string stringValue)
        {
            this.type = OptionType.String;
            this.name = GrpcPreconditions.CheckNotNull(name, "name");
            this.stringValue = GrpcPreconditions.CheckNotNull(stringValue, "stringValue");
        }

        /// <summary>
        /// Creates a channel option with an integer value.
        /// </summary>
        /// <param name="name">Name.</param>
        /// <param name="intValue">Integer value.</param>
        public ChannelOption(string name, int intValue)
        {
            this.type = OptionType.Integer;
            this.name = GrpcPreconditions.CheckNotNull(name, "name");
            this.intValue = intValue;
        }

        /// <summary>
        /// Gets the type of the <c>ChannelOption</c>.
        /// </summary>
        public OptionType Type
        {
            get
            {
                return type;
            }
        }

        /// <summary>
        /// Gets the name of the <c>ChannelOption</c>.
        /// </summary>
        public string Name
        {
            get
            {
                return name;
            }    
        }

        /// <summary>
        /// Gets the integer value the <c>ChannelOption</c>.
        /// </summary>
        public int IntValue
        {
            get
            {
                GrpcPreconditions.CheckState(type == OptionType.Integer);
                return intValue;
            }
        }

        /// <summary>
        /// Gets the string value the <c>ChannelOption</c>.
        /// </summary>
        public string StringValue
        {
            get
            {
                GrpcPreconditions.CheckState(type == OptionType.String);
                return stringValue;
            }
        }
    }

    /// <summary>
    /// Defines names of supported channel options.
    /// </summary>
    public static class ChannelOptions
    {
        /// <summary>Override SSL target check. Only to be used for testing.</summary>
        public const string SslTargetNameOverride = "grpc.ssl_target_name_override";

        /// <summary>Enable census for tracing and stats collection</summary>
        public const string Census = "grpc.census";

        /// <summary>Maximum number of concurrent incoming streams to allow on a http2 connection</summary>
        public const string MaxConcurrentStreams = "grpc.max_concurrent_streams";

        /// <summary>Maximum message length that the channel can receive</summary>
        public const string MaxReceiveMessageLength = "grpc.max_receive_message_length";

        /// <summary>Maximum message length that the channel can send</summary>
        public const string MaxSendMessageLength = "grpc.max_send_message_length";

        /// <summary>Obsolete, for backward compatibility only.</summary>
        [Obsolete("Use MaxReceiveMessageLength instead.")]
        public const string MaxMessageLength = MaxReceiveMessageLength;

        /// <summary>Initial sequence number for http2 transports</summary>
        public const string Http2InitialSequenceNumber = "grpc.http2.initial_sequence_number";

        /// <summary>Default authority for calls.</summary>
        public const string DefaultAuthority = "grpc.default_authority";

        /// <summary>Primary user agent: goes at the start of the user-agent metadata</summary>
        public const string PrimaryUserAgentString = "grpc.primary_user_agent";

        /// <summary>Secondary user agent: goes at the end of the user-agent metadata</summary>
        public const string SecondaryUserAgentString = "grpc.secondary_user_agent";

        /// <summary>If non-zero, allow the use of SO_REUSEPORT for server if it's available (default 1)</summary>
        public const string SoReuseport = "grpc.so_reuseport";

        /// <summary>
        /// Creates native object for a collection of channel options.
        /// </summary>
        /// <returns>The native channel arguments.</returns>
        internal static ChannelArgsSafeHandle CreateChannelArgs(ICollection<ChannelOption> options)
        {
            if (options == null || options.Count == 0)
            {
                return ChannelArgsSafeHandle.CreateNull();
            }
            ChannelArgsSafeHandle nativeArgs = null;
            try
            {
                nativeArgs = ChannelArgsSafeHandle.Create(options.Count);
                int i = 0;
                foreach (var option in options)
                {
                    if (option.Type == ChannelOption.OptionType.Integer)
                    {
                        nativeArgs.SetInteger(i, option.Name, option.IntValue);
                    }
                    else if (option.Type == ChannelOption.OptionType.String)
                    {
                        nativeArgs.SetString(i, option.Name, option.StringValue);
                    }
                    else 
                    {
                        throw new InvalidOperationException("Unknown option type");
                    }
                    i++;
                }
                return nativeArgs;
            }
            catch (Exception)
            {
                if (nativeArgs != null)
                {
                    nativeArgs.Dispose();
                }
                throw;
            }
        }
    }
}
