/**
 *
 * Copyright 2004 The Apache Software Foundation
 *
 *  Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 *  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.
 */
package org.apache.ws.scout.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

import javax.xml.registry.JAXRException;
import javax.xml.registry.LifeCycleManager;
import javax.xml.registry.infomodel.Association;
import javax.xml.registry.infomodel.Classification;
import javax.xml.registry.infomodel.ClassificationScheme;
import javax.xml.registry.infomodel.Concept;
import javax.xml.registry.infomodel.EmailAddress;
import javax.xml.registry.infomodel.ExternalIdentifier;
import javax.xml.registry.infomodel.ExternalLink;
import javax.xml.registry.infomodel.InternationalString;
import javax.xml.registry.infomodel.Organization;
import javax.xml.registry.infomodel.PostalAddress;
import javax.xml.registry.infomodel.RegistryObject;
import javax.xml.registry.infomodel.Service;
import javax.xml.registry.infomodel.ServiceBinding;
import javax.xml.registry.infomodel.SpecificationLink;
import javax.xml.registry.infomodel.TelephoneNumber;
import javax.xml.registry.infomodel.User;

import org.uddi.api_v3.*;
import org.apache.ws.scout.registry.infomodel.AssociationImpl;
import org.apache.ws.scout.registry.infomodel.ClassificationImpl;
import org.apache.ws.scout.registry.infomodel.ClassificationSchemeImpl;
import org.apache.ws.scout.registry.infomodel.ConceptImpl;
import org.apache.ws.scout.registry.infomodel.EmailAddressImpl;
import org.apache.ws.scout.registry.infomodel.ExternalIdentifierImpl;
import org.apache.ws.scout.registry.infomodel.ExternalLinkImpl;
import org.apache.ws.scout.registry.infomodel.InternationalStringImpl;
import org.apache.ws.scout.registry.infomodel.KeyImpl;
import org.apache.ws.scout.registry.infomodel.OrganizationImpl;
import org.apache.ws.scout.registry.infomodel.PersonNameImpl;
import org.apache.ws.scout.registry.infomodel.PostalAddressImpl;
import org.apache.ws.scout.registry.infomodel.ServiceBindingImpl;
import org.apache.ws.scout.registry.infomodel.ServiceImpl;
import org.apache.ws.scout.registry.infomodel.SpecificationLinkImpl;
import org.apache.ws.scout.registry.infomodel.TelephoneNumberImpl;
import org.apache.ws.scout.registry.infomodel.UserImpl;

/**
 * Helper class that does UDDI->Jaxr Mapping
 *
 * @author <a href="mailto:anil@apache.org">Anil Saldhana</a>
 * @author <a href="mailto:geirm@apache.org">Geir Magnusson Jr.</a>
 * @author <a href="mailto:tcunning@apache.org">Tom Cunningham</a>
 */
public class ScoutUddiV3JaxrHelper
{
	public static Association getAssociation(Collection orgs,
			LifeCycleManager lcm)
	throws JAXRException
	{
		Association asso = new AssociationImpl(lcm);
		Object[] arr = orgs.toArray();
		asso.setSourceObject((RegistryObject)arr[0]);
		asso.setTargetObject((RegistryObject)arr[1]);
		return asso;
	}

	public static Organization getOrganization(BusinessEntity businessEntity,
			LifeCycleManager lifeCycleManager)
	throws JAXRException
	{
		Organization org = new OrganizationImpl(lifeCycleManager);
		List<Name> namesList = businessEntity.getName();
		if ((namesList != null) && (namesList.size() > 0)) {
			InternationalString is = null;
			for (Name n : namesList)  {
				if (is == null) {
					is = getIString(n.getLang(), n.getValue(), lifeCycleManager);
				} else {
					is.setValue(getLocale(n.getLang()), n.getValue());
				}
			}
			org.setName(is);
		}

		List<Description> descriptionList = businessEntity.getDescription();
		if ((descriptionList != null) && (descriptionList.size() > 0)) {
			InternationalString is = null;
			for (Description desc : descriptionList)  {
				if (is == null) {
					is = getIString(desc.getLang(), desc.getValue(), lifeCycleManager);
				} else {
					is.setValue(getLocale(desc.getLang()), desc.getValue());
				}
			}
			org.setDescription(is);
		}
		org.setKey(lifeCycleManager.createKey(businessEntity.getBusinessKey()));

		//Set Services also
		BusinessServices services = businessEntity.getBusinessServices();
		if(services != null)
		{
			List<BusinessService> bizServiceList = services.getBusinessService();
			for (BusinessService businessService : bizServiceList) {
				org.addService(getService(businessService, lifeCycleManager));
			}
		}

		/*
		 *  Users
		 *
		 *  we need to take the first contact and designate as the
		 *  'primary contact'.  Currently, the OrganizationImpl
		 *  class does that automatically as a safety in case
		 *  user forgets to set - lets be explicit here as to not
		 *  depend on that behavior
		 */

		Contacts contacts = businessEntity.getContacts();
		if(contacts != null)
		{
			List<Contact> contactList = contacts.getContact();
			if (contactList!=null) {
				boolean isFirst=true;
				for (Contact contact : contactList) {
					User user = new UserImpl(null);
					List<PersonName> pname = contact.getPersonName();
					if (pname != null && pname.size() > 0) {
						String name = pname.get(0).getValue();
						user.setPersonName(new PersonNameImpl(name));						
					}
					if (isFirst) {
						isFirst=false;
						org.setPrimaryContact(user);
					} else {
						org.addUser(user);
					}
				}
			}
		}

		//External Links
		DiscoveryURLs durls = businessEntity.getDiscoveryURLs();
		if (durls != null)
		{
			List<DiscoveryURL> discoveryURL_List = durls.getDiscoveryURL();
			for (DiscoveryURL discoveryURL : discoveryURL_List) {
				ExternalLink link = new ExternalLinkImpl(lifeCycleManager);
				link.setExternalURI(discoveryURL.getValue());
				org.addExternalLink(link);
			}
		}

		org.addExternalIdentifiers(getExternalIdentifiers(businessEntity.getIdentifierBag(), lifeCycleManager));
		org.addClassifications(getClassifications(businessEntity.getCategoryBag(), lifeCycleManager));

		return org;
	}


	public static Organization getOrganization(BusinessDetail bizdetail,
			LifeCycleManager lifeCycleManager)
	throws JAXRException
	{
		List<BusinessEntity> bizEntityList = bizdetail.getBusinessEntity();
		Organization org = new OrganizationImpl(lifeCycleManager);
		if (bizEntityList.size() != 1) {
			throw new JAXRException("Unexpected count of organizations in BusinessDetail: " + bizEntityList.size());
		}
		BusinessEntity entity = bizEntityList.get(0);
		List<Name> namesList = entity.getName();
		if ((namesList != null) && (namesList.size() > 0)) {
			InternationalString is = null;
			for (Name n : namesList)  {
				if (is == null) {
					is = getIString(n.getLang(), n.getValue(), lifeCycleManager);
				} else {
					is.setValue(getLocale(n.getLang()), n.getValue());
				}
			}
			org.setName(is);
		}

		List<Description> descriptionList = entity.getDescription();
		if ((descriptionList != null) && (descriptionList.size() > 0)) {
			InternationalString is = null;
			for (Description desc : descriptionList)  {
				if (is == null) {
					is = getIString(desc.getLang(), desc.getValue(), lifeCycleManager);
				} else {
					is.setValue(getLocale(desc.getLang()), desc.getValue());
				}
			}
			org.setDescription(is);
		}
		org.setKey(lifeCycleManager.createKey(entity.getBusinessKey()));

		//Set Services also
		BusinessServices services = entity.getBusinessServices();
		if (services != null) {
			List<BusinessService> bizServiceList = services.getBusinessService();
			for (BusinessService businessService : bizServiceList) {
				org.addService(getService(businessService, lifeCycleManager));
			}
		}
			
		/*
		 *  Users
		 *
		 *  we need to take the first contact and designate as the
		 *  'primary contact'.  Currently, the OrganizationImpl
		 *  class does that automatically as a safety in case
		 *  user forgets to set - lets be explicit here as to not
		 *  depend on that behavior
		 */
		Contacts contacts = entity.getContacts();
		if (contacts != null) {
			List<Contact> contactList = contacts.getContact();
			boolean isFirst=true;
			for (Contact contact : contactList) {
				User user = new UserImpl(null);
				List<PersonName> pnames = (List<PersonName>) contact.getPersonName();
				String pname = null;
				if (pnames != null && pnames.size() > 0) {
					PersonName personname = pnames.get(0);
					pname = personname.getValue();
				}
				user.setType(contact.getUseType());
				user.setPersonName(new PersonNameImpl(pname));
	
				List<Email> emailList = contact.getEmail();
				ArrayList<EmailAddress> tempEmails = new ArrayList<EmailAddress>();
				for (Email email : emailList) {
					tempEmails.add(new EmailAddressImpl(email.getValue(), null));
				}
				user.setEmailAddresses(tempEmails);
	
				List<Address> addressList = contact.getAddress();
				ArrayList<PostalAddress> tempAddresses = new ArrayList<PostalAddress>();
				for (Address address : addressList) {
					ArrayList<AddressLine> addressLineList = new ArrayList<AddressLine>(address.getAddressLine());
					AddressLine[] alines = new AddressLine[addressLineList.size()];
					addressLineList.toArray(alines);
	
					PostalAddress pa = getPostalAddress(alines);
					tempAddresses.add(pa);
				}
				user.setPostalAddresses(tempAddresses);
	
				List<Phone> phoneList = contact.getPhone();
				ArrayList<TelephoneNumber> tempPhones = new ArrayList<TelephoneNumber>();
				for (Phone phone : phoneList) {
					TelephoneNumberImpl tni = new TelephoneNumberImpl();
					tni.setType(phone.getUseType());
					tni.setNumber(phone.getValue());
					tempPhones.add(tni);
				}
				user.setTelephoneNumbers(tempPhones);
				if (isFirst) {
					isFirst=false;
					org.setPrimaryContact(user);
				} else {
					org.addUser(user);
				}
			}
		}
		//External Links
		DiscoveryURLs durls = entity.getDiscoveryURLs();
		if (durls != null)
		{
			List<DiscoveryURL> discoveryURL_List = durls.getDiscoveryURL();
			for (DiscoveryURL discoveryURL : discoveryURL_List) {
				ExternalLink link = new ExternalLinkImpl(lifeCycleManager);
				link.setExternalURI(discoveryURL.getValue());
				org.addExternalLink(link);
			}
		}

		org.addExternalIdentifiers(getExternalIdentifiers(entity.getIdentifierBag(), lifeCycleManager));
		org.addClassifications(getClassifications(entity.getCategoryBag(), lifeCycleManager));

		return org;
	}

	private static PostalAddress getPostalAddress(AddressLine[] addressLineArr) throws JAXRException {
		PostalAddress pa = new PostalAddressImpl();
		HashMap<String, String> hm = new HashMap<String, String>();
		for (AddressLine anAddressLineArr : addressLineArr) {
			hm.put(anAddressLineArr.getKeyName(), anAddressLineArr.getValue());
		}

		if (hm.containsKey("STREET_NUMBER")) {
			pa.setStreetNumber(hm.get("STREET_NUMBER"));
		}

		if (hm.containsKey("STREET")) {
			pa.setStreet(hm.get("STREET"));
		}

		if (hm.containsKey("CITY")) {
			pa.setCity(hm.get("CITY"));
		}

		if (hm.containsKey("COUNTRY")) {
			pa.setCountry(hm.get("COUNTRY"));
		}

		if (hm.containsKey("POSTALCODE")) {
			pa.setPostalCode(hm.get("POSTALCODE"));
		}

		if (hm.containsKey("STATE")) {
			pa.setStateOrProvince(hm.get("STATE"));
		}

		return pa;
	}

	private static InternationalString getIString(String lang, String str, LifeCycleManager lifeCycleManager)
	throws JAXRException
	{
		if (str!=null) {
			return lifeCycleManager.createInternationalString(getLocale(lang), str);
		} else {
			return null;
		}
	}

	public static InternationalString getIString(String str, LifeCycleManager lifeCycleManager)
	throws JAXRException
	{
		return lifeCycleManager.createInternationalString(str);
	}

	public static Service getService(BusinessService businessService, LifeCycleManager lifeCycleManager)
	throws JAXRException
	{
		Service serve = new ServiceImpl(lifeCycleManager);

		String keystr = businessService.getServiceKey();

		if (keystr != null)
		{
			serve.setKey(lifeCycleManager.createKey(keystr));
		}

		List<Name> namesList = businessService.getName();
		InternationalString is = null;
		for (Name n : namesList) {
			if (is == null) {
				is = lifeCycleManager.createInternationalString(getLocale(n.getLang()), n.getValue());
			} else {
				is.setValue(getLocale(n.getLang()), n.getValue());
			}
		}
		serve.setName(is);
		
		List<Description> descriptionList = businessService.getDescription();
		InternationalString dis = null;
		for (Description desc : descriptionList) {
			if (dis == null) {
				dis = lifeCycleManager.createInternationalString(getLocale(desc.getLang()), desc.getValue());
			} else {
				dis.setValue(getLocale(desc.getLang()), desc.getValue());
			}
		}
		serve.setDescription(dis);

		//Populate the ServiceBindings for this Service
		BindingTemplates bts = businessService.getBindingTemplates();
		if (bts != null) {
			List<BindingTemplate> bindingTemplateList = bts.getBindingTemplate();
			for (BindingTemplate bindingTemplate : bindingTemplateList) {
				serve.addServiceBinding(getServiceBinding(bindingTemplate, lifeCycleManager));
			}
		}
		serve.addClassifications(getClassifications(businessService.getCategoryBag(), lifeCycleManager));

		return serve;
	}

	public static Service getService(ServiceInfo serviceInfo, LifeCycleManager lifeCycleManager)
	throws JAXRException
	{
		Service service = new ServiceImpl(lifeCycleManager);

		String keystr = serviceInfo.getServiceKey();

		if (keystr != null)
		{
			service.setKey(lifeCycleManager.createKey(keystr));
		}

		List<Name> namesList = serviceInfo.getName();
		InternationalString is = null;
		for (Name n : namesList) {
			if (is == null) {
				is = lifeCycleManager.createInternationalString(getLocale(n.getLang()), n.getValue());
			} else {
				is.setValue(getLocale(n.getLang()), n.getValue());
			}
		}
		service.setName(is);
		return service;
	}

	public static ServiceBinding getServiceBinding(BindingTemplate businessTemplate, LifeCycleManager lifeCycleManager)
	throws JAXRException
	{
		ServiceBinding serviceBinding = new ServiceBindingImpl(lifeCycleManager);

		String keystr = businessTemplate.getServiceKey();
		if (keystr != null)
		{
			Service svc = new ServiceImpl(lifeCycleManager);
			svc.setKey(lifeCycleManager.createKey(keystr));
			((ServiceBindingImpl)serviceBinding).setService(svc);
		}
		String bindingKey = businessTemplate.getBindingKey();
		if(bindingKey != null) serviceBinding.setKey(new KeyImpl(bindingKey));

		//Access URI
		AccessPoint access = businessTemplate.getAccessPoint();
		if (access != null) serviceBinding.setAccessURI(access.getValue());

		//Description
		Description desc = null;
		if (businessTemplate.getDescription().size()>0) desc = businessTemplate.getDescription().get(0);
		if (desc!=null) {
			serviceBinding.setDescription(new InternationalStringImpl(desc.getValue()));
		}
		/**Section D.10 of JAXR 1.0 Specification */

		TModelInstanceDetails details = businessTemplate.getTModelInstanceDetails();
		if (details != null) {
			List<TModelInstanceInfo> tmodelInstanceInfoList = details.getTModelInstanceInfo();
	
			for (TModelInstanceInfo info: tmodelInstanceInfoList)
			{
				if (info!=null && info.getInstanceDetails()!=null) {
					InstanceDetails idetails = info.getInstanceDetails();
					Collection<ExternalLink> elinks = getExternalLinks(idetails.getOverviewDoc(),lifeCycleManager);
					SpecificationLink slink = new SpecificationLinkImpl(lifeCycleManager);
					slink.addExternalLinks(elinks);
					serviceBinding.addSpecificationLink(slink); 
	
					ConceptImpl c = new ConceptImpl(lifeCycleManager);
					c.setExternalLinks(elinks);
					c.setKey(lifeCycleManager.createKey(info.getTModelKey())); 
					c.setName(lifeCycleManager.createInternationalString(idetails.getInstanceParms()));
					c.setValue(idetails.getInstanceParms());
	
					slink.setSpecificationObject(c);
				}
			}
		}
		HostingRedirector hr = businessTemplate.getHostingRedirector();
		if(hr != null)
		{
			ServiceBinding sb = lifeCycleManager.createServiceBinding();
			sb.setKey(new KeyImpl(hr.getBindingKey()));
			serviceBinding.setTargetBinding(sb);
		}
		serviceBinding.addClassifications(getClassifications(businessTemplate.getCategoryBag(), lifeCycleManager));

		return serviceBinding;
	}

	public static Concept getConcept(TModelDetail tModelDetail, LifeCycleManager lifeCycleManager)
	throws JAXRException
	{
		Concept concept = new ConceptImpl(lifeCycleManager);
		List<TModel> tmodelList = tModelDetail.getTModel();
		for (TModel tmodel : tmodelList) {
			concept.setKey(lifeCycleManager.createKey(tmodel.getTModelKey()));
			concept.setName(lifeCycleManager.createInternationalString(getLocale(tmodel.getName().getLang()),
					tmodel.getName().getValue()));

			Description desc = getDescription(tmodel);
			if( desc != null ) {
				concept.setDescription(lifeCycleManager.createInternationalString(getLocale(desc.getLang()), 
						desc.getValue()));
			}

			concept.addExternalIdentifiers(getExternalIdentifiers(tmodel.getIdentifierBag(), lifeCycleManager));
			concept.addClassifications(getClassifications(tmodel.getCategoryBag(), lifeCycleManager));
		}
		return concept;
	}

	public static Concept getConcept(TModel tmodel, LifeCycleManager lifeCycleManager)
	throws JAXRException
	{
		Concept concept = new ConceptImpl(lifeCycleManager);
		concept.setKey(lifeCycleManager.createKey(tmodel.getTModelKey()));
		concept.setName(lifeCycleManager.createInternationalString(getLocale(tmodel.getName().getLang()),
				tmodel.getName().getValue()));

		Description desc = getDescription(tmodel);
		if (desc != null) {
			concept.setDescription(lifeCycleManager.createInternationalString(getLocale(desc.getLang()), 
					desc.getValue()));
		}

		concept.addExternalIdentifiers(getExternalIdentifiers(tmodel.getIdentifierBag(), lifeCycleManager));
		concept.addClassifications(getClassifications(tmodel.getCategoryBag(), lifeCycleManager));

		return concept;
	}

	public static Concept getConcept(TModelInfo tModelInfo, LifeCycleManager lifeCycleManager)
	throws JAXRException
	{
		Concept concept = new ConceptImpl(lifeCycleManager);
		concept.setKey(lifeCycleManager.createKey(tModelInfo.getTModelKey()));
		concept.setName(lifeCycleManager.createInternationalString(getLocale(tModelInfo.getName().getLang()), 
				tModelInfo.getName().getValue()));

		return concept;
	}

	private static Description getDescription( TModel tmodel )
	{
		Description desc = null;
		if (tmodel.getDescription().size()>0) desc=tmodel.getDescription().get(0);
		return desc;
	}

	/**
	 * Classifications - going to assume all are external since UDDI does not use "Concepts".
	 * @param categoryBag categories
	 * @param lifeCycleManager lifecycleManager
	 * @return Collection Classifications
	 * @throws JAXRException on error
	 */
	public static Collection getClassifications(CategoryBag categoryBag, LifeCycleManager lifeCycleManager) 
	throws JAXRException {
		Collection<Classification> classifications = null;
		if (categoryBag != null) {
			classifications = new ArrayList<Classification>();
			List<KeyedReference> keyedReferenceList = categoryBag.getKeyedReference();
			for (KeyedReference keyedReference : keyedReferenceList) {
				Classification classification = new ClassificationImpl(lifeCycleManager);
				classification.setValue(keyedReference.getKeyValue());
				classification.setName(new InternationalStringImpl(keyedReference.getKeyName()));
				String tmodelKey = keyedReference.getTModelKey();
				if (tmodelKey != null) {
					ClassificationScheme scheme = new ClassificationSchemeImpl(lifeCycleManager);
					scheme.setKey(new KeyImpl(tmodelKey));
					classification.setClassificationScheme(scheme);
				}
				classifications.add(classification);
			}
		}
		return classifications;
	}

	public static Collection<ExternalLink> getExternalLinks(List<OverviewDoc> overviewDocs, LifeCycleManager lifeCycleManager)
	throws JAXRException
	{
		ArrayList<ExternalLink> alist = new ArrayList<ExternalLink>();
		if((overviewDocs != null) && (overviewDocs.size() != 0))
		{
			Iterator docIter = overviewDocs.iterator();
			while (docIter.hasNext()) {
				OverviewDoc overviewDoc = (OverviewDoc) docIter.next();
				String descStr = "";
				Description desc = null;
				if (overviewDoc.getDescription().size()>0) desc = overviewDoc.getDescription().get(0);
				if (desc !=null) descStr = desc.getValue();
				alist.add(lifeCycleManager.createExternalLink(overviewDoc.getOverviewURL().getValue().toString(),descStr));

			}
		}
		return alist;
	}

	/**
	 * External Identifiers
	 * @param identifierBag identifiers
	 * @param lifeCycleManager lifecycleManager
	 * @return Collection ExternalIdentifier
	 * @throws JAXRException on error
	 */

	public static Collection getExternalIdentifiers(IdentifierBag identifierBag, LifeCycleManager lifeCycleManager) 
	throws JAXRException {
		Collection<ExternalIdentifier> extidentifiers = null;
		if (identifierBag != null) {
			extidentifiers = new ArrayList<ExternalIdentifier>();

			List<KeyedReference> keyedReferenceList = identifierBag.getKeyedReference();
			for (KeyedReference keyedReference : keyedReferenceList) {
				ExternalIdentifier extId = new ExternalIdentifierImpl(lifeCycleManager);
				extId.setValue(keyedReference.getKeyValue());
				extId.setName(new InternationalStringImpl(keyedReference.getKeyName()));

				String tmodelKey = keyedReference.getTModelKey();
				if (tmodelKey != null) {
					ClassificationScheme scheme = new ClassificationSchemeImpl(lifeCycleManager);
					scheme.setKey(new KeyImpl(tmodelKey));
					extId.setIdentificationScheme(scheme);
				}
				extidentifiers.add(extId);
			}
		}
		return extidentifiers;
	}

	private static Locale getLocale(String lang) {
		if (lang == null || lang.trim().length() == 0) {
			return Locale.getDefault();
		} else if (lang.equalsIgnoreCase(Locale.getDefault().getLanguage())) {
			return Locale.getDefault();
		} else {
			return new Locale(lang);
		} 
	}

}