package org.jivesoftware.smack.provider;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.util.StringUtils;
import org.jxmpp.util.XmppStringUtils;

public final class ProviderManager {
   private static final Map<String, ExtensionElementProvider<ExtensionElement>> extensionProviders = new ConcurrentHashMap();
   private static final Map<String, IQProvider<IQ>> iqProviders = new ConcurrentHashMap();
   private static final Map<String, ExtensionElementProvider<ExtensionElement>> streamFeatureProviders = new ConcurrentHashMap();

   public static void addLoader(ProviderLoader loader) {
      Iterator i$;
      if (loader.getIQProviderInfo() != null) {
         i$ = loader.getIQProviderInfo().iterator();

         while(i$.hasNext()) {
            IQProviderInfo info = (IQProviderInfo)i$.next();
            addIQProvider(info.getElementName(), info.getNamespace(), info.getProvider());
         }
      }

      if (loader.getExtensionProviderInfo() != null) {
         i$ = loader.getExtensionProviderInfo().iterator();

         while(i$.hasNext()) {
            ExtensionProviderInfo info = (ExtensionProviderInfo)i$.next();
            addExtensionProvider(info.getElementName(), info.getNamespace(), info.getProvider());
         }
      }

      if (loader.getStreamFeatureProviderInfo() != null) {
         i$ = loader.getStreamFeatureProviderInfo().iterator();

         while(i$.hasNext()) {
            StreamFeatureProviderInfo info = (StreamFeatureProviderInfo)i$.next();
            addStreamFeatureProvider(info.getElementName(), info.getNamespace(), (ExtensionElementProvider)info.getProvider());
         }
      }

   }

   public static IQProvider<IQ> getIQProvider(String elementName, String namespace) {
      String key = getKey(elementName, namespace);
      return (IQProvider)iqProviders.get(key);
   }

   public static List<IQProvider<IQ>> getIQProviders() {
      List<IQProvider<IQ>> providers = new ArrayList(iqProviders.size());
      providers.addAll(iqProviders.values());
      return providers;
   }

   public static void addIQProvider(String elementName, String namespace, Object provider) {
      validate(elementName, namespace);
      String key = removeIQProvider(elementName, namespace);
      if (provider instanceof IQProvider) {
         iqProviders.put(key, (IQProvider)provider);
      } else {
         throw new IllegalArgumentException("Provider must be an IQProvider");
      }
   }

   public static String removeIQProvider(String elementName, String namespace) {
      String key = getKey(elementName, namespace);
      iqProviders.remove(key);
      return key;
   }

   public static ExtensionElementProvider<ExtensionElement> getExtensionProvider(String elementName, String namespace) {
      String key = getKey(elementName, namespace);
      return (ExtensionElementProvider)extensionProviders.get(key);
   }

   public static void addExtensionProvider(String elementName, String namespace, Object provider) {
      validate(elementName, namespace);
      String key = removeExtensionProvider(elementName, namespace);
      if (provider instanceof ExtensionElementProvider) {
         extensionProviders.put(key, (ExtensionElementProvider)provider);
      } else {
         throw new IllegalArgumentException("Provider must be a PacketExtensionProvider");
      }
   }

   public static String removeExtensionProvider(String elementName, String namespace) {
      String key = getKey(elementName, namespace);
      extensionProviders.remove(key);
      return key;
   }

   public static List<ExtensionElementProvider<ExtensionElement>> getExtensionProviders() {
      List<ExtensionElementProvider<ExtensionElement>> providers = new ArrayList(extensionProviders.size());
      providers.addAll(extensionProviders.values());
      return providers;
   }

   public static ExtensionElementProvider<ExtensionElement> getStreamFeatureProvider(String elementName, String namespace) {
      String key = getKey(elementName, namespace);
      return (ExtensionElementProvider)streamFeatureProviders.get(key);
   }

   public static void addStreamFeatureProvider(String elementName, String namespace, ExtensionElementProvider<ExtensionElement> provider) {
      validate(elementName, namespace);
      String key = getKey(elementName, namespace);
      streamFeatureProviders.put(key, provider);
   }

   public static void removeStreamFeatureProvider(String elementName, String namespace) {
      String key = getKey(elementName, namespace);
      streamFeatureProviders.remove(key);
   }

   private static String getKey(String elementName, String namespace) {
      return XmppStringUtils.generateKey(elementName, namespace);
   }

   private static void validate(String elementName, String namespace) {
      if (StringUtils.isNullOrEmpty(elementName)) {
         throw new IllegalArgumentException("elementName must not be null or empty");
      } else if (StringUtils.isNullOrEmpty(namespace)) {
         throw new IllegalArgumentException("namespace must not be null or empty");
      }
   }

   static {
      SmackConfiguration.getVersion();
   }
}
