/*
 * 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.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using Nehta.VendorLibrary.Common;
using Nehta.VendorLibrary.PCEHR;
using Nehta.VendorLibrary.PCEHR.GetView;
using Nehta.VendorLibrary.PCEHR.PrescriptionAndDispenseView;
using Nehta.VendorLibrary.PCEHR.HealthRecordOverview;
using Nehta.VendorLibrary.PCEHR.PathologyReportView;

namespace PCEHR.Sample
{
    /// <summary>
    /// Sample demonstrating how to use the 'GetAuditViewClient' client.
    /// </summary>
    public class GetViewClientSample
    {
        public void SampleForCdaDocumentResponses()
        {
            // Obtain the certificate for use with TLS and signing
            X509Certificate2 cert = X509CertificateUtil.GetCertificate(
                "Serial Number",
                X509FindType.FindBySerialNumber,
                StoreName.My,
                StoreLocation.CurrentUser,
                true
                );

            // Create PCEHR header
            CommonPcehrHeader header = PcehrHeaderHelper.CreateHeader();

            // Instantiate the client
            GetViewClient getViewClient = new GetViewClient(new Uri("https://GetViewEndpoint"), cert, cert);

            // Add server certificate validation callback
            ServicePointManager.ServerCertificateValidationCallback += ValidateServiceCertificate;

            try
            {
                getView request = new getView()
                {
                    // Creates a PrescriptionAndDispenseView
                    view = new prescriptionAndDispenseView()
                    {
                        fromDate = DateTime.Now.AddDays(-10),
                        toDate = DateTime.Now,
                        versionNumber = "Version number here"
                    }

                    // Other types of views can be created using these classes
                    // Nehta.VendorLibrary.PCEHR.PrescriptionAndDispenseView.prescriptionAndDispenseView
                    // Nehta.VendorLibrary.PCEHR.MedicareOverview.medicareOverview
                    // Nehta.VendorLibrary.PCEHR.HealthCheckScheduleView.healthCheckScheduleView
                    // Nehta.VendorLibrary.PCEHR.ObservationView.observationView
                    // Nehta.VendorLibrary.PCEHR.AdvanceCareInformationView.advanceCareInformationView
                    // Nehta.VendorLibrary.PCEHR.HealthRecordOverview.healthRecordOverview
                    // Nehta.VendorLibrary.PCEHR.PathologyIndexView.pathologyIndexView
                    // Nehta.VendorLibrary.PCEHR.DiagnosticImagingReportView.diagnosticImagingReportView
                };

                var responseStatus = getViewClient.GetView(header, request);


                // Get the soap request and response
                string soapRequest = getViewClient.SoapMessages.SoapRequest;
                string soapResponse = getViewClient.SoapMessages.SoapResponse;
            }
            catch (FaultException fex)
            {
                // Handle any errors
            }
        }

        public void SampleForXmlResponses()
        {
            // Obtain the certificate for use with TLS and signing
            X509Certificate2 cert = X509CertificateUtil.GetCertificate(
                "Serial Number",
                X509FindType.FindBySerialNumber,
                StoreName.My,
                StoreLocation.CurrentUser,
                true
                );

            // Create PCEHR header
            CommonPcehrHeader header = PcehrHeaderHelper.CreateHeader();

            // Instantiate the client
            GetViewClient getViewClient = new GetViewClient(new Uri("https://GetViewEndpoint"), cert, cert);

            // Add server certificate validation callback
            ServicePointManager.ServerCertificateValidationCallback += ValidateServiceCertificate;

            try
            {
                getView request = new getView()
                {
                    // Creates a advanceCarePlanningView
                    view = new pathologyReportView()
                    {
                        versionNumber = "Version number here"
                    }

                    // Other types of views can be created using these classes
                    // using Nehta.VendorLibrary.PCEHR.DiagnosticImagingReportView;
                    // using Nehta.VendorLibrary.PCEHR.PathologyIndexView;
                };

                var responseStatus = getViewClient.GetView(header, request);

                // Convert XML response into Class for advanceCarePlanningView
                XmlDocument xml = new XmlDocument();
                xml.PreserveWhitespace = true;
                xml.LoadXml(Encoding.Default.GetString(responseStatus.view.data));
                pathologyReportViewResponse data = new pathologyReportViewResponse();
                data = (pathologyReportViewResponse)DeserialiseElementToClass(xml.DocumentElement, data);

                // Get the soap request and response
                string soapRequest = getViewClient.SoapMessages.SoapRequest;
                string soapResponse = getViewClient.SoapMessages.SoapResponse;
            }
            catch (FaultException fex)
            {
                // Handle any errors
            }
        }

        public void SampleForHroResponse()
        {
            // Obtain the certificate for use with TLS and signing
            X509Certificate2 cert = X509CertificateUtil.GetCertificate(
                "Serial Number",
                X509FindType.FindBySerialNumber,
                StoreName.My,
                StoreLocation.CurrentUser,
                true
                );

            // Create PCEHR header
            CommonPcehrHeader header = PcehrHeaderHelper.CreateHeader();

            // Instantiate the client
            GetViewClient getViewClient = new GetViewClient(new Uri("https://GetViewEndpoint"), cert, cert);

            // Add server certificate validation callback
            ServicePointManager.ServerCertificateValidationCallback += ValidateServiceCertificate;

            try
            {
                getView request = new getView()
                {
                    view = new healthRecordOverView()
                    {
                        clinicalSynopsisLength = 200
                    }
                };

                var responseStatus = getViewClient.GetView(header, request);

                // Convert XML response into Class for healthRecordOverview
                XmlDocument xml = new XmlDocument();
                xml.PreserveWhitespace = true;
                xml.LoadXml(Encoding.Default.GetString(responseStatus.view.data));
                healthRecordOverviewResponse data = new healthRecordOverviewResponse();
                data = (healthRecordOverviewResponse)DeserialiseElementToClass(xml.DocumentElement, data);

                // Get the soap request and response
                string soapRequest = getViewClient.SoapMessages.SoapRequest;
                string soapResponse = getViewClient.SoapMessages.SoapResponse;
            }
            catch (FaultException fex)
            {
                // Handle any errors
            }
        }

        private bool ValidateServiceCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            // Checks can be done here to validate the service certificate.
            // If the service certificate contains any problems or is invalid, return false. Otherwise, return true.
            // This example returns true to indicate that the service certificate is valid.
            return true;
        }

        private static object DeserialiseElementToClass(XmlElement element, object doctype)
        {
            XmlDocument doc = new XmlDocument();
            doc.AppendChild(doc.ImportNode(element, true));
            XmlReader read = doc.CreateNavigator().ReadSubtree();
            XmlRootAttribute rootAttr = new XmlRootAttribute(element.LocalName);
            rootAttr.Namespace = element.NamespaceURI;
            XmlSerializer xs = new XmlSerializer(doctype.GetType(), rootAttr);
            object rv = xs.Deserialize(read);
            return (rv);
        }


    }
}
