using System.Collections.Generic;
using System.Diagnostics;
using System;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Net;
namespace Renci.SshNet
{
    /// 
    /// Collection of different extension method
    /// 
    public static partial class Extensions
    {
        /// 
        /// Checks whether a collection is the same as another collection
        /// 
        /// The current instance object
        /// The collection to compare with
        /// The comparer object to use to compare each item in the collection.  If null uses EqualityComparer(T).Default
        /// True if the two collections contain all the same items in the same order
        internal static bool IsEqualTo(this IEnumerable value, IEnumerable compareList, IEqualityComparer comparer)
        {
            if (value == compareList)
                return true;
            if (value == null || compareList == null)
                return false;
            if (comparer == null)
            {
                comparer = EqualityComparer.Default;
            }
            var enumerator1 = value.GetEnumerator();
            var enumerator2 = compareList.GetEnumerator();
            bool enum1HasValue = enumerator1.MoveNext();
            bool enum2HasValue = enumerator2.MoveNext();
            try
            {
                while (enum1HasValue && enum2HasValue)
                {
                    if (!comparer.Equals(enumerator1.Current, enumerator2.Current))
                    {
                        return false;
                    }
                    enum1HasValue = enumerator1.MoveNext();
                    enum2HasValue = enumerator2.MoveNext();
                }
                return !(enum1HasValue || enum2HasValue);
            }
            finally
            {
                enumerator1.Dispose();
                enumerator2.Dispose();
            }
        }
        /// 
        /// Checks whether a collection is the same as another collection
        /// 
        /// The current instance object
        /// The collection to compare with
        /// True if the two collections contain all the same items in the same order
        internal static bool IsEqualTo(this IEnumerable value, IEnumerable compareList)
        {
            return IsEqualTo(value, compareList, null);
        }
#if SILVERLIGHT
#else
        /// 
        /// Prints out 
        /// 
        /// The bytes.
        internal static void DebugPrint(this IEnumerable bytes)
        {
            foreach (var b in bytes)
            {
                Debug.Write(string.Format(CultureInfo.CurrentCulture, "0x{0:x2}, ", b));
            }
            Debug.WriteLine(string.Empty);
        }
#endif
        /// 
        /// Trims the leading zero from bytes array.
        /// 
        /// The data.
        /// Data without leading zeros.
        internal static IEnumerable TrimLeadingZero(this IEnumerable data)
        {
            bool leadingZero = true;
            foreach (var item in data)
            {
                if (item == 0 & leadingZero)
                {
                    continue;
                }
                leadingZero = false;
                yield return item;
            }
        }
        /// 
        /// Creates an instance of the specified type using that type's default constructor.
        /// 
        /// The type to create.
        /// Type of the instance to create.
        /// A reference to the newly created object.
        internal static T CreateInstance(this Type type) where T : class
        {
            if (type == null)
                return null;
            return Activator.CreateInstance(type) as T;
        }
        /// 
        /// Returns the specified 16-bit unsigned integer value as an array of bytes.
        /// 
        /// The number to convert.
        /// An array of bytes with length 2.
        internal static byte[] GetBytes(this UInt16 value)
        {
            return new byte[] { (byte)(value >> 8), (byte)(value & 0xFF) };
        }
        /// 
        /// Returns the specified 32-bit unsigned integer value as an array of bytes.
        /// 
        /// The number to convert.
        /// An array of bytes with length 4.
        internal static byte[] GetBytes(this UInt32 value)
        {
            return new byte[] { (byte)(value >> 24), (byte)(value >> 16), (byte)(value >> 8), (byte)(value & 0xFF) };
        }
        /// 
        /// Returns the specified 64-bit unsigned integer value as an array of bytes.
        /// 
        /// The number to convert.
        /// An array of bytes with length 8.
        internal static byte[] GetBytes(this UInt64 value)
        {
            return new byte[] { (byte)(value >> 56), (byte)(value >> 48), (byte)(value >> 40), (byte)(value >> 32), (byte)(value >> 24), (byte)(value >> 16), (byte)(value >> 8), (byte)(value & 0xFF) };
        }
        /// 
        /// Returns the specified 64-bit signed integer value as an array of bytes.
        /// 
        /// The number to convert.
        /// An array of bytes with length 8.
        internal static byte[] GetBytes(this Int64 value)
        {
            return new byte[] { (byte)(value >> 56), (byte)(value >> 48), (byte)(value >> 40), (byte)(value >> 32), (byte)(value >> 24), (byte)(value >> 16), (byte)(value >> 8), (byte)(value & 0xFF) };
        }
#if SILVERLIGHT
        private static Regex _rehost = new Regex(@"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$", RegexOptions.IgnoreCase);
        private static Regex _reIPv6 = new Regex(@"^(((?=(?>.*?::)(?!.*::)))(::)?([0-9A-F]{1,4}::?){0,5}|([0-9A-F]{1,4}:){6})(\2([0-9A-F]{1,4}(::?|$)){0,2}|((25[0-5]|(2[0-4]|1\d|[1-9])?\d)(\.|$)){4}|[0-9A-F]{1,4}:[0-9A-F]{1,4})(?.*?::)(?!.*::)))(::)?([0-9A-F]{1,4}::?){0,5}|([0-9A-F]{1,4}:){6})(\2([0-9A-F]{1,4}(::?|$)){0,2}|((25[0-5]|(2[0-4]|1\d|[1-9])?\d)(\.|$)){4}|[0-9A-F]{1,4}:[0-9A-F]{1,4})(? IPEndPoint.MaxPort)
                return false;
            return true;
        }
        internal static bool IsValidPort(this int value)
        {
            if (value < IPEndPoint.MinPort)
                return false;
            if (value > IPEndPoint.MaxPort)
                return false;
            return true;
        }
    }
}