/*
 * Copyright 2012 NEHTA
 *
 * Licensed under the NEHTA Open Source (Apache) License; you may not use this
 * file except in compliance with the License. A copy of the License is in the
 * 'license.txt' file, which should be provided with this work.
 *
 * 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.
 */

using System;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Channels;
using Nehta.VendorLibrary.Common;
using Nehta.VendorLibrary.PCEHR.DocumentRegistry;

namespace Nehta.VendorLibrary.PCEHR
{
    /// <summary>
    /// DocumentRegistryClient.
    /// </summary>
    internal class DocumentRegistryClient
    {
        /// <summary>
        /// Generated client.
        /// </summary>
        internal DocumentRegistry_PortTypeClient documentRegistryClient;

        /// <summary>
        /// Contains the request and response SOAP messages after an invocation is made.
        /// </summary>
        internal SoapMessages soapMessages;

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="endpointUri">Service endpoint.</param>
        /// <param name="signingCert">Header signing certificate.</param>
        /// <param name="tlsCert">TLS client certificate.</param>
        internal DocumentRegistryClient(Uri endpointUri, X509Certificate2 signingCert, X509Certificate2 tlsCert)
        {
            Validation.ValidateArgumentRequired("endpointUri", endpointUri);

            InitialiseClient(endpointUri.ToString(), null, signingCert, tlsCert);
        }

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="endpointConfigurationName">Configuration name.</param>
        /// <param name="signingCert">Header signing certificate.</param>
        /// <param name="tlsCert">TLS client certificate.</param>
        internal DocumentRegistryClient(string endpointConfigurationName, X509Certificate2 signingCert, X509Certificate2 tlsCert)
        {
            Validation.ValidateArgumentRequired("endpointConfigurationName", endpointConfigurationName);

            InitialiseClient(null, endpointConfigurationName, signingCert, tlsCert);
        }

        /// <summary>
        /// Close the client.
        /// </summary>
        internal void Close()
        {
            documentRegistryClient.Close();
        }

        /// <summary>
        /// Gets a document list based on a query.
        /// </summary>
        /// <param name="pcehrHeader">PCEHR header.</param>
        /// <param name="queryRequest">Query request.</param>
        /// <returns>Query response.</returns>
        internal AdhocQueryResponse GetDocumentList(PCEHRHeader pcehrHeader, AdhocQueryRequest queryRequest)
        {
            var timestamp = new timestampType()
            {
                created = DateTime.Now
            };

            var signatureContainer = new signatureContainerType();

            return documentRegistryClient.DocumentRegistry_RegistryStoredQuery(timestamp, ref signatureContainer, pcehrHeader, queryRequest);
        }

        /// <summary>
        /// Uploads document metadata.
        /// </summary>
        /// <param name="pcehrHeader">PCEHR header.</param>
        /// <param name="submitObjectsRequest">Metadata.</param>
        /// <returns>Response.</returns>
        internal RegistryResponseType UploadDocumentMetadata(PCEHRHeader pcehrHeader, SubmitObjectsRequest submitObjectsRequest)
        {
            var timestamp = new timestampType()
            {
                created = DateTime.Now
            };

            var signatureContainer = new signatureContainerType();

            return documentRegistryClient.DocumentRegistry_RegisterDocumentSetb(timestamp, ref signatureContainer, pcehrHeader, submitObjectsRequest);
        }

        /// <summary>
        /// Initialises the client endpoint.
        /// </summary>
        /// <param name="endpointUri">Service endpoint.</param>
        /// <param name="endpointConfigurationName">Configuration name.</param>
        /// <param name="signingCert">Header signing certificate.</param>
        /// <param name="tlsCert">TLS client certificate.</param>
        private void InitialiseClient(string endpointUri, string endpointConfigurationName, X509Certificate2 signingCert, X509Certificate2 tlsCert)
        {
            Validation.ValidateArgumentRequired("tlsCert", tlsCert);

            soapMessages = new SoapMessages();

            DocumentRegistry_PortTypeClient client = null;

            if (!string.IsNullOrEmpty(endpointUri))
            {
                EndpointAddress address = new EndpointAddress(endpointUri);
                CustomBinding tlsBinding = BindingHelper.CreateTlsBinding();

                client = new DocumentRegistry_PortTypeClient(tlsBinding, address);
            }
            else if (!string.IsNullOrEmpty(endpointConfigurationName))
            {
                client = new DocumentRegistry_PortTypeClient(endpointConfigurationName);
            }

            if (client != null)
            {
                PCEHREndpointProcessor.ProcessEndpoint(client.Endpoint, signingCert, soapMessages);

                if (tlsCert != null)
                {
                    client.ClientCredentials.ClientCertificate.Certificate = tlsCert;
                }

                documentRegistryClient = client;
            }
        }

    }
}
