package org.inria.bmajwatcher.server.data;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;
import org.inria.biomaj.singleton.BiomajInformation;
import org.inria.biomaj.utils.BiomajException;

/**
 * Retrieves bank properties from a remote repository.
 * 
 * @author rsabas
 *
 */
public class RemoteBankRetriever {

	private Map<String, Properties> remoteBanks = new HashMap<String, Properties>();
	private static Logger log = Logger.getLogger(RemoteBankRetriever.class);
	
	public List<String> getRemoteBankList(String url) {
		remoteBanks.clear();
		Pattern pattern = Pattern.compile("href=[\"'](.+\\.properties)[\"']");
		try {
			URL repository = new URL(url);
			BufferedReader br = new BufferedReader(new InputStreamReader(repository.openStream()));
			String line;
			while ((line = br.readLine()) != null) {
				Matcher match = pattern.matcher(line);
				while (match.find()) {
					String bankUrl = match.group(1);
					Properties props;
					if (!remoteBanks.containsKey(getBankName(bankUrl))
							&& (props = readRemoteProperties(url, match.group(1))) != null) {
						remoteBanks.put(getBankName(bankUrl), props);
					}
				}
			}
			br.close();
		} catch (MalformedURLException e) {
			e.printStackTrace();
			log.error(e);
		} catch (IOException e) {
			e.printStackTrace();
			log.error(e);
		}
		
		List<String> res = new ArrayList<String>();
		res.addAll(remoteBanks.keySet());
		return res;
	}
	
	public Properties getBankOnlyProperties(String bankName) {
		return remoteBanks.get(bankName);
	}
	
	public Properties getAllBankProperties(String bankName) {
		Properties props = remoteBanks.get(bankName);
		Properties global = new Properties();
		loadDefaultProperties(global);
		Properties res = new Properties();
		for (Object key : global.keySet()) {
			res.put(key, global.get(key));
		}
		for (Object key : props.keySet())
			res.put(key, props.get(key));
		
		return res;
	}
	
	private void loadDefaultProperties(Properties props) {
		try {
			File file = new File(BiomajInformation.getInstance().getProperty(BiomajInformation.WORKFLOWSDIR) + "/global.properties");
			try {
				props.load(new FileReader(file));
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		} catch (BiomajException e1) {
			e1.printStackTrace();
		}
	}
	
	private Properties readRemoteProperties(String parentUrl, String url) {
		try {
			URL bank = new URL(url);
			Properties props = new Properties();			
			props.load(bank.openStream());
			return props;
		} catch (MalformedURLException e) {
			log.error(e);
			if (!parentUrl.isEmpty()) {
				log.info("Trying with URL base...");
				return readRemoteProperties("", getBaseURL(parentUrl) + "/" + url);
			}
		} catch (IOException e) {
			log.error(e);
		}
		
		return null;
	}
	
	private String getBaseURL(String url) {
		int index;
		if ((index = url.indexOf("://")) < 0)
			index = 0;
		int endIndex;
		if ((endIndex = url.indexOf("/", index + 3)) < 0)
			return url;
		else
			return url.substring(0, endIndex);
	}
	
	private String getBankName(String url) {
		return url.substring(url.lastIndexOf("/") + 1, url.lastIndexOf('.'));
	}
}
