package cz.muni.fi.lasaris.sbms.data.logic;

import java.util.NavigableMap;
import java.util.Properties;
import java.util.TreeMap;

import org.apache.log4j.Logger;

import cz.muni.fi.lasaris.sbms.data.providers.TrendsProvider;
import cz.muni.fi.lasaris.sbms.data.providers.DataPointsProvider;


public class ProviderManager {
	final static Logger logger = Logger.getLogger(ProviderManager.class);
	private static NavigableMap<String,TrendsProvider> trendsProviders;
	private static NavigableMap<String,DataPointsProvider> dpsProviders;
	
	public static void init(Properties props) {
		trendsProviders = new TreeMap<String,TrendsProvider>();
		dpsProviders = new TreeMap<String,DataPointsProvider>();
			
		String bcs = props.getProperty("data.providers.datapoints");
		
		// starting DP providers first - some archive connectors might be dependent on them
		if(bcs != null) {
			for(String bc : bcs.split(",")) {
				String bct = bc.trim();
				String bcc = props.getProperty(String.format("data.providers.datapoints.%s.class", bct));
				//String prefix = props.getProperty(String.format("data.providers.bas.$s.prefix", bc.trim()));
				try {
					if(bcc == null) {
						throw new IllegalArgumentException(String.format("Class for the BAS connector %s is not set.", bct));
					}
					Class<?>c = Class.forName(bcc);
					DataPointsProvider bci = (DataPointsProvider)c.newInstance();
					ProviderManager.dpsProviders.put(bct, bci);
					bci.init(props, bct, String.format("data.providers.datapoints.%s", bct));
					logger.debug(String.format("BAS connector %s initialized.", bct));
				} catch (Exception e) {
					logger.error(String.format("Unable to create BAS connector %s.", bct), e);
				}
				
			}
		} else {
			throw new IllegalArgumentException(String.format("Unable to initialize BAS data providers - none specified"));
		}
		
		
		String acs = props.getProperty("data.providers.trends");
		
		if(acs != null) {
			for(String ac : acs.split(",")) {
				String act = ac.trim();
				String acc = props.getProperty(String.format("data.providers.trends.%s.class", act));
				try {
					if(acc == null) {
						throw new IllegalArgumentException(String.format("Class for the Archive connector %s is not set.", act));
					}
				//String prefix = props.getProperty(String.format("data.providers.bas.$s.prefix", bc.trim()));
				Class<?> c = Class.forName(acc);
				TrendsProvider aci = (TrendsProvider)c.newInstance();
				ProviderManager.trendsProviders.put(act, aci);
				aci.init(props, act, String.format("data.providers.trends.%s", act));
				logger.debug(String.format("Archive connector %s initialized.", act));
				} catch (Exception e) {
					logger.error(String.format("Unable to create Archive connector %s.", act), e);
				}
			}
		} else {
			throw new IllegalArgumentException(String.format("Unable to initialize Archive data providers - none specified"));
		}
	}
	
	public static DataPointsProvider getDataPointsProvider(String name) {
		if(ProviderManager.dpsProviders == null) {
			throw new IllegalStateException("Data points connectors not set");
		}
		if(name == null || dpsProviders.size() == 1 || name.equals("") || !dpsProviders.containsKey(name)) name = dpsProviders.firstKey();
		return dpsProviders.get(name);
	}
	
	public static TrendsProvider getTrendsProvider(String name) {
		if(ProviderManager.trendsProviders == null) {
			throw new IllegalStateException("Trends connectors not set");
		}
		if(name == null || trendsProviders.size() == 1 || name.equals("") || !trendsProviders.containsKey(name)) name = trendsProviders.firstKey();
		return trendsProviders.get(name);
	}
	
	public static void close() {
		for(DataPointsProvider c : dpsProviders.values()) {
			c.close();
		}
		for(TrendsProvider c : trendsProviders.values()) {
			c.close();
		}
	}
}
