/*
  * 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 compl,iance 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 System.Xml.Serialization;

using dk.gov.oiosi.common.cache;
using dk.gov.oiosi.addressing;
using dk.gov.oiosi.uddi.category;
using dk.gov.oiosi.uddi.identifier;
using dk.gov.oiosi.exception;


namespace dk.gov.oiosi.uddi {

    /// <summary>
    /// Options for the lookup.
    /// </summary>
    public enum LookupReturnOptionEnum {

        /// <summary>
        /// Throws an exceptions if not either one or zero results were returned.
        /// </summary>
        [XmlEnum("noMoreThanOneSetOrFail")]
        noMoreThanOneSetOrFail,

        /// <summary>
        /// If multiple results were returned from the UDDI inquiry, return only the first
        /// </summary>
        [XmlEnum("firstResult")]
        firstResult,

        /// <summary>
        /// Return all results from the UDDI inquiry
        /// </summary>
        [XmlEnum("allResults")]
        allResults
    }

    /// <summary>
    /// If more than one type of endpoint is returned from the UDDI lookup, which scheme is preferred?
    /// </summary>
    public enum PreferredEndpointType { 
        /// <summary>
        /// A HTTP endpoint
        /// </summary>
        [XmlEnum("http")]
        http,

        /// <summary>
        /// A mail endpoint
        /// </summary>
        [XmlEnum("mailto")]
        mailto    
    }

    /// <summary>
    /// Holds a set of parameters and options for a specific lookup call.
    /// </summary>
    public class LookupParameters {

        /// <summary>
        /// The key and key type of the endpoint.
        /// </summary>
        private IIdentifier _endpointKey;

        /// <summary>
        /// The key of the endpoint.
        /// </summary>
        public IIdentifier EndpointKey {
            get { return _endpointKey; }
        }

        private EndpointKeytype _endpointKeyType;

        /// <summary>
        /// Gets the keytype of the endpoint
        /// </summary>
        public EndpointKeytype EndpointKeyType {
            get { return _endpointKeyType; }
        }

        private UddiId _serviceContractTModel;

        /// <summary>
        /// The UDDI uuid of the tModel representing the service contract. This is not the uuid of the endpoint
        /// tModel, but of the central service definition tModel, e.g. the central electronic invoice endpoint 
        /// tModel. 
        /// </summary>
        public UddiId ServiceContractTModel {
            get { return _serviceContractTModel; }
        }

        private UddiId _businessProcessDefinitionTModel;

        /// <summary>
        /// The UDDI uuid of the tModel representing the business process definition.
        /// </summary>
        public UddiId BusinessProcessDefinitionTModel {
            get { return _businessProcessDefinitionTModel; }
        }

        /// <summary>
        /// The type of the business process role identifier
        /// </summary>
        private BusinessProcessRoleIdentifierType _roleIdentifierType;

        /// <summary>
        /// The type of the business process role identifier
        /// </summary>
        public BusinessProcessRoleIdentifierType RoleIdentifierType {
            get { return _roleIdentifierType; }
        }

        /// <summary>
        /// The business process role identifier
        /// </summary>
        private BusinessProcessRoleIdentifier _roleIdentifier;

        /// <summary>
        /// The preferred scheme of the endpoint
        /// </summary>
        PreferredEndpointType _preferredEndpointType;

        /// <summary>
        /// The business process role identifier
        /// </summary>
        public BusinessProcessRoleIdentifier RoleIdentifier {
            get { return _roleIdentifier; }
        }

        /// <summary>
        /// Registration conformance claim. Instantiated with default claim
        /// (OIOSI 1.0 UddiRegistrationModel)
        /// </summary>
        private RegistrationConformanceClaim _registrationConformanceClaim = 
            new RegistrationConformanceClaim(RegistrationConformanceClaimCode.oiosi1_1);

        private ConformanceClaim _profileConformanceClaim =
            new ConformanceClaim(ConformanceClaimCode.secureReliableAsyncProfile1_0);

        /// <summary>
        /// The value of the UDDI registration conformance claim custom identifier keyedReference value.
        /// </summary>
        public RegistrationConformanceClaim RegistrationConformanceClaim {
            get { return _registrationConformanceClaim; }
        }

        /// <summary>
        /// The value of the profile registration conformance claim custom identifier 
        /// keyedReference value. Set to the default (RASP 1.0 profile)
        /// </summary>
        public ConformanceClaim ProfileConformanceClaim {
            get { return _profileConformanceClaim; }
        }

        private List<EndpointAddressTypeCode> _addressTypeFilter;

        /// <summary>
        /// List of endpoint address types that may be returned in the search.
        /// If this property is null or empty, all address types should be returned.
        /// </summary>
        public List<EndpointAddressTypeCode> AddressTypeFilter {
            get { return _addressTypeFilter; }
        }


        private LookupReturnOptionEnum _lookupReturnOption = LookupReturnOptionEnum.allResults;

        /// <summary>
        /// The return semantics of the Lookup() operation. See the LookupReturnOptionEnum for details.
        /// </summary>
        public LookupReturnOptionEnum LookupReturnOption {
            get { return _lookupReturnOption; }
        }

        
        /// <summary>
        /// The preferred scheme of the endpoint returned
        /// </summary>
        public PreferredEndpointType PreferredEndpointType {
            get { return _preferredEndpointType; }
        }

        private ITimedCache<LookupKey, List<UddiLookupResponse>> _lookupCache = new TimedNullCache<LookupKey, List<UddiLookupResponse>>();

        /// <summary>
        /// The caching model to use in uddi lookups.
        /// The default is no cache.
        /// </summary>
        public ITimedCache<LookupKey, List<UddiLookupResponse>> LookupCache {
            get { return _lookupCache; }
            set {
                if (value == null) {
                    throw new NullArgumentException("value was null");
                }
                _lookupCache = value;
            }
        }
        

        /// <summary>
        /// Constructor. 
        /// </summary>
        /// <param name="endpointKey">The endpoint key</param>
        /// <param name="endpointKeyType">The type of the endpoint key</param>
        /// <param name="addressTypeFilter">List of endpoint address types that should be returned in the search.
        /// If this property is null or empty, all address types should be returned.</param>
        /// <param name="preferredEndpointType">The preferred type of endpoint address, e.g. http or email</param>
        /// <param name="lookupReturnOption">Set the return semantics of the Lookup() operation. 
        /// See the LookupReturnOptionEnum for details.</param>
        /// <param name="serviceContractTModel">The UDDI id of the tModel representing the service contract</param>
        /// <param name="roleIdentifierType">The type of process role identifier. 
        /// If this value is null, the roleIdentifier must also be null</param>
        /// <param name="roleIdentifier">The type of the process role identifier. 
        /// If this value is null, the roleIdentifierType must also be null</param>
        /// <param name="processDefinitionTModel">The UDDI id of the tModel representing the 
        /// business process definition</param>
        public LookupParameters(
            IIdentifier endpointKey,
            EndpointKeytype endpointKeyType,
            List<EndpointAddressTypeCode> addressTypeFilter,
            PreferredEndpointType preferredEndpointType,
            LookupReturnOptionEnum lookupReturnOption,
            UddiId serviceContractTModel,
            BusinessProcessRoleIdentifierType roleIdentifierType,
            BusinessProcessRoleIdentifier roleIdentifier,
            UddiId processDefinitionTModel
        ) {
            // Note that addressTypeFilter is allowed to be null or empty.
            _addressTypeFilter = addressTypeFilter;
            _lookupReturnOption = lookupReturnOption;
            _endpointKey = endpointKey;
            _endpointKeyType = endpointKeyType;
            _serviceContractTModel = serviceContractTModel;
            _roleIdentifierType = roleIdentifierType;
            _roleIdentifier = roleIdentifier;
            _businessProcessDefinitionTModel = processDefinitionTModel;
            _preferredEndpointType = preferredEndpointType;
        }


        /// <summary>
        /// Compares the object members that constitutes a look up key and returns true if the two objects have the same key
        /// </summary>
        /// <param name="lookupParameters"></param>
        /// <returns></returns>
        public bool HasKeyValueEqualTo(LookupParameters lookupParameters) {
            if (this._addressTypeFilter != lookupParameters._addressTypeFilter) return false;
            if (this._businessProcessDefinitionTModel != lookupParameters._businessProcessDefinitionTModel) return false;
            if (this._endpointKey != lookupParameters._endpointKey) return false;
            if (this._endpointKeyType != lookupParameters._endpointKeyType) return false;
            if (this._profileConformanceClaim != lookupParameters._profileConformanceClaim) return false;
            if (this._registrationConformanceClaim != lookupParameters._registrationConformanceClaim) return false;
            if (this._roleIdentifier != lookupParameters._roleIdentifier) return false;
            if (this._serviceContractTModel != lookupParameters._serviceContractTModel) return false;

            return true;
        }

        /// <summary>
        /// Returns the lookup key object used in the timed UDDI cache
        /// </summary>
        /// <returns>Returns the lookup key object used in the timed UDDI cache</returns>
        public LookupKey GetLookupKey() {
            LookupKey lookupKey = new LookupKey(
                _addressTypeFilter,
                _businessProcessDefinitionTModel,
                _endpointKey,
                _endpointKeyType,
                _profileConformanceClaim,
                _registrationConformanceClaim,
                _roleIdentifier,
                _serviceContractTModel
                );
            return lookupKey;
        }
    }

}
