using System;
using System.Diagnostics;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using ChannelAdam.ServiceModel;
using Valg.EVA.Skanning.ServicesModel.Internal.SystemSettings;

namespace Valg.EVA.Skanning.ServicesModel.Internal.UploadWebService
{
    public class UploadWebServiceFactory : IUploadWebServiceFactory
    {
        private readonly string productionCertificateIssuerParams; 
        private readonly string trainingCertificateIssuerParams; 

        public UploadWebServiceFactory(ISystemSettingsProvider systemSettings)
        {
            productionCertificateIssuerParams = systemSettings.GetProductionCertificateIssuerParams();
            trainingCertificateIssuerParams = systemSettings.GetTrainingCertificateIssuerParams();
        }

        private GenericFileUploadWSClient CreateClientWithCertificate(string endpointConfigurationName)
        {
            var client = new GenericFileUploadWSClient(endpointConfigurationName);
            
            
            client.ClientCredentials.ClientCertificate.Certificate = FindClientCertificate();
            return client;
        }

        public IServiceConsumer<GenericFileUploadWS> CreateTransferClient()
        {
            return ServiceConsumerFactory.Create<GenericFileUploadWS>(() => CreateClientWithCertificate("TransferWebService"));
        }

        public IServiceConsumer<GenericFileUploadWS> CreateCheckStatusClient()
        {
            return ServiceConsumerFactory.Create<GenericFileUploadWS>(() => CreateClientWithCertificate("TransferWebServiceCheckStatus"));
        }

        class DebugFaultLogger : IEndpointBehavior, IClientMessageInspector
        {
            public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
            {
            }

            public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
            {
                clientRuntime.MessageInspectors.Add(this);
            }

            public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
            {
            }

            public void Validate(ServiceEndpoint endpoint)
            {
            }

            public void AfterReceiveReply(ref Message reply, object correlationState)
            {
                if (reply.IsFault)
                {
                    Trace.TraceError("Fault received!: {0}", reply);
                }
            }

            public object BeforeSendRequest(ref Message request, IClientChannel channel)
            {
                return null;
            }
        }


        
        
        
        
        
        
        
        
        
        
        private X509Certificate2 FindClientCertificate()
        {
            var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
          
            try
            {
                store.Open(OpenFlags.ReadOnly);
               
                var validCertificates = store.Certificates.Find(X509FindType.FindByTimeValid, DateTime.Now, false);
                var findType = X509FindType.FindByIssuerDistinguishedName;
                var matchingCertificate = validCertificates.Find(findType, productionCertificateIssuerParams, false);

                if (matchingCertificate.Count == 0)
                {
                    matchingCertificate = validCertificates.Find(findType, trainingCertificateIssuerParams, false);
                }

                return matchingCertificate.Count > 0 ? matchingCertificate[0] : null;
            }
            finally
            {
                store.Close();
            }
        }
    }
}

