/*
  * 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.addressing;
using System.Security.Cryptography.X509Certificates;
using dk.gov.oiosi.oioublProfileLibrary.Exceptions;

namespace dk.gov.oiosi.oioublProfileLibrary {

    /// <summary>
    /// Factory class used to create or retrieve a Business Entity
    /// </summary>
    public class OioublBusinessEntityFactory {
        
        /// <summary>
        /// Creates a new BusinessEntity in the UDDI registry
        /// </summary>
        /// <param name="cvr">The BusinessEntity CVR number</param>
        /// <param name="name">The BusinessEntity name</param>
        /// <param name="description">The description of the BusinessEntity</param>
        /// <param name="employeeCertificate">A valid employee certificate</param>
        /// <param name="endpointCertificate">A valid device- or company certificate</param>
        /// <returns>The created BusinessEntity</returns>
        public static IOioublBusinessEntity CreateBusinessEntity(
            string cvr, 
            string name, 
            string description, 
            X509Certificate2 employeeCertificate,
            X509Certificate2 endpointCertificate
        ) {
            OioublProfileLibrarySettings.SetUddiCredentials(employeeCertificate);

            RegistrationConformanceClaim registrationConformanceClaim = new RegistrationConformanceClaim(RegistrationConformanceClaimCode.oiosi1_1);
            OIOTaxonomy oioTaxonomy = new OIOTaxonomy("OIO subject scheme / TRADE AND INDUSTRY / E-COMMERCE /", "uddi:ea4bc88f-9479-4f9b-a354-4acabdb99336");
            OrganizationKey key = new OrganizationKey(new IdentifierCvr(cvr));

            OrganizationKeyType organizationKeyType = new OrganizationKeyType(OrganizationKeyTypeCode.cvrNumber);
            UddiContactSimple businessEntityContact = new UddiContactSimple();
            businessEntityContact.PersonName = name;

            UddiDiscoveryUrl discoveryUrl = null;
            Name businessName = new Name(name);
            Description businessDescription = new Description(description);

            ArsBusinessEntity arsBusinessEntity = new ArsBusinessEntity();
            arsBusinessEntity.SetBusinessEntityDetails(registrationConformanceClaim,
                oioTaxonomy, key, organizationKeyType, businessEntityContact, discoveryUrl,
                businessName, businessDescription);
            arsBusinessEntity.Save();
                        
            IOioublBusinessEntity businessEntity = new OioublBusinessEntity(arsBusinessEntity, cvr, endpointCertificate);
            return businessEntity;
        }

        /// <summary>
        /// Returns a BusinessEntity from the UDDI registry.
        /// If the BusinessEntity is not found, an exception is thrown.
        /// If more than one BusinessEntity is found, an exception is thrown.
        /// </summary>
        /// <param name="cvr">The CVR number to look for</param>
        /// <param name="employeeCertificate">A valid employee certificate</param>
        /// <param name="endpointCertificate">A valid device or company certificate</param>
        /// <returns>The found BusinessEntity</returns>
        public static IOioublBusinessEntity GetBusinessEntity(
            string cvr, 
            X509Certificate2 employeeCertificate,
            X509Certificate2 endpointCertificate
        ) {
            IOioublBusinessEntity businessEntity;
            if (!TryGetBusinessEntity(cvr, employeeCertificate, endpointCertificate, out businessEntity)) {
                string messsage = "BusinessEntity with CVR not found: " + cvr;
                throw new BusinessEntityNotFoundException(cvr);
            }
            return businessEntity;
        }

        /// <summary>
        /// Returns a BusinessEntity from the UDDI registry.
        /// If the BusinessEntity is not found, an exception is thrown.
        /// If more than one BusinessEntity is found, an exception is thrown.
        /// </summary>
        /// <param name="name">The name to look for</param>
        /// <param name="employeeCertificate">A valid employee certificate</param>
        /// <param name="endpointCertificate">A valid device- or company certificate</param>
        /// <returns>The found BusinessEntity</returns>
        public static IOioublBusinessEntity GetBusinessEntityByName(
            string name, 
            X509Certificate2 employeeCertificate,
            X509Certificate2 endpointCertificate
        ) {
            List<businessInfo> businessEntities = ArsLookup.FindArsBusinessEntities(name);

            string uddiId = businessEntities[0].businessKey;
            UddiGuidId id = new UddiGuidId(uddiId, true);
            ArsBusinessEntity entity = ArsBusinessEntity.Get(id, true);

            return new OioublBusinessEntity(entity, entity.OrganizationKey.Value, endpointCertificate);
        }

        /// <summary>
        /// Returns a BusinessEntity from the UDDI registry.
        /// If the BusinessEntity is not found, an exception is thrown.
        /// If more than one BusinessEntity is found, an exception is thrown.
        /// </summary>
        /// <param name="cvr">The CVR number to look for</param>
        /// <param name="employeeCertificate">A valid employee certificate</param>
        /// <param name="endpointCertificate">A valid device- or company certificate</param>
        /// <param name="businessEntity">Outputs the business entity</param>
        /// <returns>True if the BusinessEntity was found. False if the Business was not found or more than one BusinessEntity was found.</returns>
        public static bool TryGetBusinessEntity(
            string cvr, 
            X509Certificate2 employeeCertificate, 
            X509Certificate2 endpointCertificate,
            out IOioublBusinessEntity businessEntity
        ) {
            businessEntity = null;
            OioublProfileLibrarySettings.SetUddiCredentials(employeeCertificate);
            List<businessInfo> businessEntities = ArsLookup.FindArsBusinessEntitiesByCvr(cvr);
            if (businessEntities.Count == 0) return false;
            if (businessEntities.Count > 1)
                throw new CvrNumberNotUniqueException(cvr);
            string uddiId = businessEntities[0].businessKey;
            UddiGuidId id = new UddiGuidId(uddiId, true);
            ArsBusinessEntity entity = ArsBusinessEntity.Get(id, true);
            businessEntity = new OioublBusinessEntity(entity, cvr, endpointCertificate);
            return true;
        }
    }
}
