package edu.ucsb.nceas.metacat.dataone.hazelcast;

import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.dataone.service.types.v1.Identifier;

import com.hazelcast.core.MapLoader;

import edu.ucsb.nceas.metacat.IdentifierManager;
import edu.ucsb.nceas.metacat.McdbDocNotFoundException;
import edu.ucsb.nceas.metacat.properties.PropertyService;
import edu.ucsb.nceas.metacat.shared.ServiceException;
import edu.ucsb.nceas.utilities.FileUtil;
import edu.ucsb.nceas.utilities.PropertyNotFoundException;


/**
 * MapLoader implementation for a hazelcast hzObjectPath.  This class is called
 * when the ObjectPathMap needs to refresh against the persistent datastore.
 * The use case for this class is to communicate the filepath between JVMs on
 * the same machine, specifically between the metacat instance and the d1_indexer.
 * 
 * d1_indexer will get Identifiers from elsewhere, but use this class to get
 * the paths to their associated files.  The getAllKeys() method can (and should)
 * return null in a live setting.  For unit testing, it may be useful to use
 * it to get some 
 * 
 * @author rnahf
 *
 */
public class MockObjectPathMap implements MapLoader<Identifier, String> {
	private static IdentifierManager im;
	private static String dataPath;
	private static String metadataPath;
	
	
	/**
	 * creates an ObjectPathMap
	 */
	public MockObjectPathMap() {
//		try {
//			PropertyService ps = PropertyService.getInstance();
//			dataPath = PropertyService.getProperty("application.datafilepath");
//			metadataPath = PropertyService.getProperty("application.documentfilepath");
//		} catch (PropertyNotFoundException e) {
//			// TODO Autogenerated catch block
//			e.printStackTrace();
//		} catch (ServiceException e) {
//			// TODO Autogenerated catch block
//			e.printStackTrace();
//		}
		dataPath = "/data/";
		metadataPath = "/metadata/";
		im = IdentifierManager.getInstance();
	}

	
	/*
	 * Metadata is stored in a different place on the filesystem than
	 * the data.  The doctype value for metadata can vary, but for data
	 * is always 'BIN', so using a simple ifthenelse to separate
	 */
	private String pathToDocid(String localid) throws McdbDocNotFoundException  {
		
		return "/some/path/" + localid; 
//		Hashtable<String, Object> ht = im.getDocumentInfo(localid);
//		if (ht.get("doctype").equals("BIN")) {
//			return dataPath + FileUtil.getFS() + localid;
//		} else {
//			return metadataPath + FileUtil.getFS() + localid;
//		}		
	}

	
	/**
	 *  Implementation of hazelcast MapLoader interface method.
	 *  For the provided Identifier (as key), returns the path to the
	 *  document on the local filesystem.  Returns null if it can't 
	 *  create the path. 
	 */
	@Override
	public String load(Identifier key) 
	{

		String docid = null;
		String path = null;
		//			try {
		//				docid = im.getLocalId(key.getValue());
		//				path = pathToDocid(docid);			
		//			} catch (McdbDocNotFoundException e) {
		//				// TODO Autogenerated catch block
		//				e.printStackTrace();
		//				return null;
		//			}
		if (key.getValue().startsWith("NO_CREATE")) {
			return null;
		}
		path = "/path/" + key.getValue();
		return path;
	}
	
	
	/**
	 *  Implementation of hazelcast MapLoader interface method.  This method loads
	 *  mappings for all Identifiers in the parameters.  Any Identifier not found
	 *  is not included in the resulting map.
	 */
	@Override
	public Map<Identifier, String> loadAll(Collection<Identifier> identifiers) {
		
		
		Hashtable<Identifier,String> map = new Hashtable<Identifier,String>();
		for (Identifier id : identifiers) {
			map.put(id, "/path/" + id.getValue());
			//				try {
			//					String docid = im.getLocalId(id.getValue());
			//					map.put(id, pathToDocid(docid));
			//
			//				} catch (McdbDocNotFoundException e) {
			//					// TODO should the map load an empty path instead of
			//					// leaving out the entire entry?
			//					e.printStackTrace();
			//				}
		}
		return map;
	}

	
	/**
	 * Return the full set of guids in the local metacat repository as
	 * dataone Identifiers.
	 * 
	 * (Hazelcast allows avoiding preloading by returning NULL, so consider
	 * reimplementing if that serves the purpose of this class better)
	 */
	@Override
	public Set<Identifier> loadAllKeys() 
	{
		//		List<String> guids = im.getAllGUIDs();
		//		
		Set<Identifier> set = Collections.synchronizedSet(new HashSet<Identifier>());
		//		for (String guid : guids) {
		//			Identifier id = new Identifier();
		//			id.setValue(guid);
		//			set.add(id);
		//		}

		for (int i=1; i< 100; i++) {
			Identifier id = new Identifier();
			id.setValue("testID." + i);
			set.add(id);
		}
		return set;
		
	}
}