/*
  * The contents of this file are subject to the Mozilla Public
  * License Version 1.1 (the "License"); you may not use this
  * file except in compliance with the License. You may obtain
  * a copy of the License at http://www.mozilla.org/MPL/
  *
  * Software distributed under the License is distributed on an
  * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
  * or implied. See the License for the specific language governing
  * rights and limitations under the License.
  *
  *
  * The Original Code is .NET RASP toolkit.
  *
  * The Initial Developer of the Original Code is Accenture and Avanade.
  * Portions created by Accenture and Avanade are Copyright (C) 2007
  * Danish National IT and Telecom Agency (http://www.itst.dk). 
  * All Rights Reserved.
  *
  * Contributor(s):
  *   Gert Sylvest (gerts@avanade.com)
  *   Patrik Johansson (p.johansson@accenture.com)
  *   Michael Nielsen (michaelni@avanade.com)
  *   Dennis Søgaard (dennis.j.sogaard@accenture.com)
  *   Ramzi Fadel (ramzif@avanade.com)
  *   Mikkel Hippe Brun (mhb@itst.dk)
  *   Finn Hartmann Jordal (fhj@itst.dk)
  *   Christian Lanng (chl@itst.dk)
  *
  */
using System;
using System.Collections.Generic;
using System.Text;

using dk.gov.oiosi.uddi;
using dk.gov.oiosi.uddi.ars;
using dk.gov.oiosi.uddi.category;
using dk.gov.oiosi.uddi.identifier;
using dk.gov.oiosi.common;


namespace dk.gov.oiosi.oioublProfileLibrary {
    
    /// <summary>
    /// Factory class for creating OioublBinding instances
    /// </summary>
    internal class OioublBindingFactory {

        /// <summary>
        /// Creates a new instance of an OioublBinding.
        /// </summary>
        /// <param name="businessEntity">The BusinessEntity that owns the binding.</param>
        /// <param name="oioublProfile">The profile to reference from the binding.</param>
        /// <param name="serviceDefinition">The ServiceDefinition the binding supports.</param>
        /// <param name="oioublEndpointAddressType">The address type (HTTP, SMTP, ...)</param>
        /// <param name="endpointAddress">The binding's address URI</param>
        /// <returns>Returns a new OioublBinding</returns>
        public static OioublBinding CreateOioublBinding (
            IOioublBusinessEntity businessEntity,
            IOioublProfile oioublProfile,
            OioublServiceDefinition serviceDefinition,
            OioublEndpointAddressType oioublEndpointAddressType,
            string endpointAddress) {
            
            ArsBinding arsBinding = CreateArsBinding(oioublProfile, serviceDefinition, businessEntity,
                oioublEndpointAddressType, endpointAddress);

            OioublBinding oioublBinding = new OioublBinding(arsBinding);
            return oioublBinding;
        }

        /// <summary>
        /// Creates an ArsBinding with an associated ArsProcessInstance.
        /// The ArsProcessInstance is created with a reference to the process definition defined in the profile
        /// </summary>
        /// <param name="oioublProfile">The profile this binding implements</param>
        /// <param name="oioublServiceDefinition">The service definition the bindind references</param>
        /// <param name="businessEntity">The business entity that owns the binding</param>
        /// <param name="oioublEndpointAddressType">The address type of the binding (http, smtp, ...)</param>
        /// <param name="endpointAddress">The address (URI) of the binding</param>
        /// <returns>Returns a created ArsBinding</returns>
        private static ArsBinding CreateArsBinding(
            IOioublProfile oioublProfile,
            OioublServiceDefinition oioublServiceDefinition,
            IOioublBusinessEntity businessEntity, 
            OioublEndpointAddressType oioublEndpointAddressType, 
            string endpointAddress) {


            // Create an ArsProcessInstance that references the process definition definedin the profile
            ArsProcessInstanceSet processInstanceSet = CreateArsProcessInstanceSet(oioublProfile);

            OasisServiceSingleBindingRegistration serviceReference = new OasisServiceSingleBindingRegistration();
            EndpointAddressType endpointAddressType = OioublEndpointAddress.GetArsEndpointAddressType(oioublEndpointAddressType);
            serviceReference.Transport = endpointAddressType;

            AccessPoint accessPoint = new AccessPoint(new Uri(endpointAddress));
            EndpointAddressType addressType = OioublEndpointAddress.GetArsEndpointAddressType(oioublEndpointAddressType);
            UddiId businessKeyUddiId = IdentifierUtility.GetUddiIDFromString(businessEntity.UddiId);

            OasisBindingRegistrationReference bindingReference = new OasisBindingRegistrationReference();
            bindingReference.ID = oioublServiceDefinition.GetBindingRegistrationReferenceUddiId( oioublEndpointAddressType);

            // This is the servicedefinition
            OasisPortTypeRegistrationReference portTypeReference = new OasisPortTypeRegistrationReference();
            portTypeReference.ID = oioublServiceDefinition.UddiId;

            serviceReference.BindingRegistrationRef = bindingReference;
            serviceReference.PortTypeRegistrationRef = portTypeReference;

            Description bindingDescription = GetDescription(oioublEndpointAddressType);

            ArsBinding arsBinding = new ArsBinding(processInstanceSet, serviceReference, accessPoint,
                addressType, bindingDescription, businessKeyUddiId, null);
            
            arsBinding.AccessPoint.AccessEndpointUri = new Uri(endpointAddress);
            return arsBinding;
        }

        private static ArsProcessInstanceSet CreateArsProcessInstanceSet(IOioublProfile oioublProfile) {
            ArsProcessInstanceSet arsProcessInstanceSet = new ArsProcessInstanceSet();
            
            OioublProcessInstance oioublProcessInstance = new OioublProcessInstance(oioublProfile);
            arsProcessInstanceSet.Add(oioublProcessInstance.CreateArsProcessInstance());
            arsProcessInstanceSet.Save();

            return arsProcessInstanceSet;
        }

        
        private static Description GetDescription(OioublEndpointAddressType oioublEndpointAddressType) {
            string endpointAddressTypeString = OioublEndpointAddress.GetEndpointAddressTypeString(oioublEndpointAddressType);
            Description bindingDescription = new Description(endpointAddressTypeString + " binding");
            return bindingDescription;
        }

    }
}
