package com.palacesun.engine.spy;

import com.palacesun.engine.common.P6LogQuery;
import com.palacesun.engine.common.P6Util;
import com.palacesun.engine.spy.option.EnvironmentVariables;
import com.palacesun.engine.spy.option.P6OptionChangedListener;
import com.palacesun.engine.spy.option.P6OptionsRepository;
import com.palacesun.engine.spy.option.P6OptionsSource;
import com.palacesun.engine.spy.option.SpyDotProperties;
import com.palacesun.engine.spy.option.SystemProperties;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanRegistrationException;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;

public class P6ModuleManager {
   private final P6OptionsSource[] optionsSources = new P6OptionsSource[]{new SpyDotProperties(), new EnvironmentVariables(), new SystemProperties()};
   private final Map<Class<? extends P6LoadableOptions>, P6LoadableOptions> allOptions = new HashMap();
   private final List<P6Factory> factories = new CopyOnWriteArrayList();
   private final P6MBeansRegistry mBeansRegistry = new P6MBeansRegistry();
   private final P6OptionsRepository optionsRepository = new P6OptionsRepository();
   private static P6ModuleManager instance;

   private static synchronized void initMe() {
      try {
         cleanUp();
         instance = new P6ModuleManager();
         P6LogQuery.initialize();
      } catch (Exception e) {
         handleInitEx(e);
      }

   }

   private static void cleanUp() throws MBeanRegistrationException, InstanceNotFoundException, MalformedObjectNameException, Exception {
      if (instance != null) {
         for(P6OptionsSource optionsSource : instance.optionsSources) {
            optionsSource.preDestroy(instance);
         }

         if (P6SpyOptions.getActiveInstance().getJmx() && instance.mBeansRegistry != null) {
            instance.mBeansRegistry.unregisterAllMBeans(P6SpyOptions.getActiveInstance().getJmxPrefix());
         }

         new DefaultJdbcEventListenerFactory();
         DefaultJdbcEventListenerFactory.clearCache();
      }
   }

   private P6ModuleManager() throws IOException, MBeanRegistrationException, NotCompliantMBeanException, MalformedObjectNameException, InstanceNotFoundException, ClassCastException {
      this.debug(this.getClass().getName() + " re/initiating modules started");
      this.registerOptionChangedListener(new P6LogQuery());
      P6SpyLoadableOptions spyOptions = (P6SpyLoadableOptions)this.registerModule(new P6SpyFactory());
      this.loadDriversExplicitly(spyOptions);
      Set<P6Factory> moduleFactories = spyOptions.getModuleFactories();
      if (null != moduleFactories) {
         try {
            for(Object data : spyOptions.getModuleFactories()) {
               if (data == null) {
                  System.out.println("a:null");
               }
            }
         } catch (Exception var8) {
         }

         try {
            for(P6Factory factory : spyOptions.getModuleFactories()) {
               this.registerModule(factory);
            }
         } catch (Exception var7) {
         }
      }

      this.optionsRepository.initCompleted();
      this.mBeansRegistry.registerMBeans(this.allOptions.values());

      for(P6OptionsSource optionsSource : this.optionsSources) {
         optionsSource.postInit(this);
      }

      this.debug(this.getClass().getName() + " re/initiating modules done");
   }

   protected synchronized P6LoadableOptions registerModule(P6Factory factory) {
      try {
         for(P6Factory registeredFactory : this.factories) {
            if (registeredFactory.getClass().equals(factory.getClass())) {
               return null;
            }
         }
      } catch (Exception var4) {
      }

      P6LoadableOptions options = factory.getOptions(this.optionsRepository);
      this.loadOptions(options);
      this.factories.add(factory);
      this.debug("Registered factory: " + factory.getClass().getName() + " with options: " + options.getClass().getName());
      return options;
   }

   private void loadOptions(P6LoadableOptions options) {
      options.load(options.getDefaults());

      for(P6OptionsSource optionsSource : this.optionsSources) {
         Map<String, String> toLoad = optionsSource.getOptions();
         if (null != toLoad) {
            options.load(toLoad);
         }
      }

      this.allOptions.put(options.getClass(), options);
   }

   public static P6ModuleManager getInstance() {
      return instance;
   }

   private static void handleInitEx(Exception e) {
      e.printStackTrace(System.err);
   }

   private void loadDriversExplicitly(P6SpyLoadableOptions spyOptions) {
      Collection<String> driverNames = spyOptions.getDriverNames();
      if (null != driverNames) {
         for(String driverName : driverNames) {
            try {
               P6Util.forName(driverName).newInstance();
            } catch (Exception var6) {
            }
         }
      }

   }

   private void debug(String msg) {
      if (instance != null && !this.factories.isEmpty()) {
         P6LogQuery.debug(msg);
      }
   }

   public <T extends P6LoadableOptions> T getOptions(Class<T> optionsClass) {
      return (T)(this.allOptions.get(optionsClass));
   }

   public void reload() {
      initMe();
   }

   public List<P6Factory> getFactories() {
      return this.factories;
   }

   public void registerOptionChangedListener(P6OptionChangedListener listener) {
      this.optionsRepository.registerOptionChangedListener(listener);
   }

   public void unregisterOptionChangedListener(P6OptionChangedListener listener) {
      this.optionsRepository.unregisterOptionChangedListener(listener);
   }

   static {
      initMe();
   }
}
