package com.sun.identity.plugin.datastore;

import com.sun.identity.common.SystemConfigurationUtil;
import com.sun.identity.shared.debug.Debug;
import com.sun.identity.shared.locale.Locale;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;

public final class DataStoreProviderManager {
   public static final String DEFAULT = "default";
   public static final String PROVIDER_ATTR_PREFIX = "com.sun.identity.plugin.datastore.class.";
   public static final String DEFAULT_PROVIDER_ATTR = "com.sun.identity.plugin.datastore.class.default";
   private final Map<String, DataStoreProvider> providerMap;
   private DataStoreProvider defaultProvider;
   private static final DataStoreProviderManager INSTANCE = new DataStoreProviderManager();
   private final Debug debug = Debug.getInstance("libPlugins");
   private final ResourceBundle bundle = Locale.getInstallResourceBundle("libDataStoreProvider");

   private DataStoreProviderManager() {
      this.providerMap = new HashMap<>();

      try {
         this.defaultProvider = this.getDefaultProvider();
         this.defaultProvider.init("default");
      } catch (DataStoreProviderException de) {
         this.debug.error("DataStoreProviderManager: exception obtaining default provider:", de);
      }
   }

   public static DataStoreProviderManager getInstance() throws DataStoreProviderException {
      return INSTANCE;
   }

   public DataStoreProvider getDataStoreProvider(String componentName) throws DataStoreProviderException {
      if (componentName != null && !componentName.isEmpty()) {
         DataStoreProvider provider = this.providerMap.get(componentName);
         if (provider != null) {
            return provider;
         }

         String className = SystemConfigurationUtil.getProperty("com.sun.identity.plugin.datastore.class." + componentName);
         if (className != null && !className.isEmpty()) {
            try {
               provider = (DataStoreProvider)Class.forName(className).getDeclaredConstructor().newInstance();
            } catch (Exception e) {
               this.debug.error("DataStoreProviderManager.getDataStoreProvider: exception while instantiating provider:" + className + ":", e);
               throw new DataStoreProviderException(e);
            }
         }

         if (provider == null) {
            if (this.debug.messageEnabled()) {
               this.debug.message("DataStoreProviderManager.getDataStoreProvider: no provider specified for " + componentName + ", using default.");
            }

            provider = this.getDefaultProvider();
         }

         provider.init(componentName);
         synchronized (this.providerMap) {
            this.providerMap.put(componentName, provider);
            return provider;
         }
      } else {
         return this.defaultProvider;
      }
   }

   private DataStoreProvider getDefaultProvider() throws DataStoreProviderException {
      String className = SystemConfigurationUtil.getProperty("com.sun.identity.plugin.datastore.class.default");
      if (className != null && !className.isEmpty()) {
         try {
            return (DataStoreProvider)Class.forName(className).getDeclaredConstructor().newInstance();
         } catch (Exception e) {
            throw new DataStoreProviderException(e);
         }
      } else {
         throw new DataStoreProviderException(this.bundle.getString("defaultProviderNotDefined"));
      }
   }
}
