#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;

using Grpc.Core.Internal;

namespace Grpc.Core
{
    /// <summary>
    /// gRPC Channel
    /// </summary>
    public class Channel : IDisposable
    {
        readonly GrpcEnvironment environment;
        readonly ChannelSafeHandle handle;
        readonly List<ChannelOption> options;
        readonly string target;
        bool disposed;

        /// <summary>
        /// Creates a channel that connects to a specific host.
        /// Port will default to 80 for an unsecure channel and to 443 a secure channel.
        /// </summary>
        /// <param name="host">The DNS name of IP address of the host.</param>
        /// <param name="credentials">Credentials to secure the channel.</param>
        /// <param name="options">Channel options.</param>
        public Channel(string host, Credentials credentials, IEnumerable<ChannelOption> options = null)
        {
            this.environment = GrpcEnvironment.GetInstance();
            this.options = options != null ? new List<ChannelOption>(options) : new List<ChannelOption>();

            EnsureUserAgentChannelOption(this.options);
            using (CredentialsSafeHandle nativeCredentials = credentials.ToNativeCredentials())
            using (ChannelArgsSafeHandle nativeChannelArgs = ChannelOptions.CreateChannelArgs(this.options))
            {
                if (nativeCredentials != null)
                {
                    this.handle = ChannelSafeHandle.CreateSecure(nativeCredentials, host, nativeChannelArgs);
                }
                else
                {
                    this.handle = ChannelSafeHandle.CreateInsecure(host, nativeChannelArgs);
                }
            }
            this.target = GetOverridenTarget(host, this.options);
        }

        /// <summary>
        /// Creates a channel that connects to a specific host and port.
        /// </summary>
        /// <param name="host">DNS name or IP address</param>
        /// <param name="port">the port</param>
        /// <param name="credentials">Credentials to secure the channel.</param>
        /// <param name="options">Channel options.</param>
        public Channel(string host, int port, Credentials credentials, IEnumerable<ChannelOption> options = null) :
            this(string.Format("{0}:{1}", host, port), credentials, options)
        {
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        internal string Target
        {
            get
            {
                return target;
            }
        }

        internal ChannelSafeHandle Handle
        {
            get
            {
                return this.handle;
            }
        }

        internal CompletionQueueSafeHandle CompletionQueue
        {
            get
            {
                return this.environment.CompletionQueue;
            }
        }

        internal CompletionRegistry CompletionRegistry
        {
            get
            {
                return this.environment.CompletionRegistry;
            }
        }

        internal GrpcEnvironment Environment
        {
            get
            {
                return this.environment;
            }
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing && handle != null && !disposed)
            {
                disposed = true;
                handle.Dispose();
            }
        }

        private static void EnsureUserAgentChannelOption(List<ChannelOption> options)
        {
            if (!options.Any((option) => option.Name == ChannelOptions.PrimaryUserAgentString))
            {
                options.Add(new ChannelOption(ChannelOptions.PrimaryUserAgentString, GetUserAgentString()));
            }
        }

        private static string GetUserAgentString()
        {
            // TODO(jtattermusch): it would be useful to also provide .NET/mono version.
            return string.Format("grpc-csharp/{0}", VersionInfo.CurrentVersion);
        }

        /// <summary>
        /// Look for SslTargetNameOverride option and return its value instead of originalTarget
        /// if found.
        /// </summary>
        private static string GetOverridenTarget(string originalTarget, IEnumerable<ChannelOption> options)
        {
            if (options == null)
            {
                return originalTarget;
            }
            foreach (var option in options)
            {
                if (option.Type == ChannelOption.OptionType.String
                    && option.Name == ChannelOptions.SslTargetNameOverride)
                {
                    return option.StringValue;
                }
            }
            return originalTarget;
        }
    }
}
