using GostCryptography.Base;
using System;
using System.Linq;
using System.Security.Cryptography.X509Certificates;

namespace Hcs.ClientNet.Internal
{
    internal static class CertificateHelper
    {
        internal static bool IsGostPrivateKey(this X509Certificate2 certificate)
        {
            try
            {
                if (certificate.HasPrivateKey)
                {
                    var cspInfo = certificate.GetPrivateKeyInfo();
                    if (cspInfo.ProviderType == (int)ProviderType.CryptoPro ||
                        cspInfo.ProviderType == (int)ProviderType.VipNet ||
                        cspInfo.ProviderType == (int)ProviderType.CryptoPro_2012_512 ||
                        cspInfo.ProviderType == (int)ProviderType.CryptoPro_2012_1024)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                return false;
            }
            catch
            {
                return false;
            }
        }

        internal static GostXades.CryptoProviderTypeEnum GetProviderType(this X509Certificate2 certificate)
        {
            return (GostXades.CryptoProviderTypeEnum)GetProviderInfo(certificate).Item1;
        }

        internal static Tuple<int, string> GetProviderInfo(this X509Certificate2 certificate)
        {
            if (certificate.HasPrivateKey)
            {
                var cspInfo = certificate.GetPrivateKeyInfo();
                return new Tuple<int, string>(cspInfo.ProviderType, cspInfo.ProviderName);
            }
            else
            {
                throw new Exception("Certificate has no private key");
            }
        }

        internal static X509Certificate2 FindCertificate(Func<X509Certificate2, bool> predicate)
        {
            if (predicate == null)
            {
                throw new ArgumentException("Null subject predicate");
            }

            var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
            try
            {
                store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);

                var collection = store.Certificates
                    .OfType<X509Certificate2>()
                    .Where(x => x.HasPrivateKey && x.IsGostPrivateKey());

                var now = DateTime.Now;
                return collection.First(
                    x => now >= x.NotBefore && now <= x.NotAfter && predicate(x));
            }
            finally
            {
                store.Close();
            }
        }
    }
}
