package utils;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import models.Shapefile.ShapeFeature;

import org.mapdb.BTreeKeySerializer;
import org.mapdb.BTreeMap;
import org.mapdb.DB;
import org.mapdb.DBMaker;
import org.mapdb.Fun;
import org.mapdb.Pump;
import org.mapdb.Fun.Tuple2;

import controllers.Application;
import play.Logger;
import play.Play;

public class DataStore<T> {

	DB db;
	Map<String,T> map;
	
	/** Create a new data store in the default location with transactional support enabled and the default cache */
	public DataStore(String dataFile) {
	
		this(new File(Application.dataPath), dataFile, true, false);
	}

	/**
	 * Create a new datastore with transactional support enabled and a default cache.
	 */
	public DataStore(File directory, String dataFile) {
		this(directory, dataFile, true, false);
	}
	
	/**
	 * Create a new DataStore.
	 * @param directory Where should it be created?
	 * @param dataFile What should it be called?
	 * @param transactional Should MapDB's transactional support be enabled?
	 * @param weakRefCache Should we use a weak reference cache instead of the default fixed-size cache?
	 */
	public DataStore(File directory, String dataFile, boolean transactional, boolean weakRefCache) {
	
		if(!directory.exists())
			directory.mkdirs();
		
		try {
			Logger.info(directory.getCanonicalPath());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		DBMaker dbm = DBMaker.newFileDB(new File(directory, dataFile + ".db"))
			// make it fast, we need this so we don't have queues backing up during multipoint jobs
		    // note that on a 32 bit machine this will fall back to random access files
			// and the writes will be slow, mailboxes may back up, OOME's may occur, etc.
		    // on a 32bit machine, proceed at your own risk.
			//.mmapFileEnableIfSupported()
			.closeOnJvmShutdown();
		
		if (!transactional)
			dbm = dbm.transactionDisable();
		
		if (weakRefCache)
			dbm = dbm.cacheWeakRefEnable();
		
	    db = dbm.make();
		
		map = db.getTreeMap(dataFile);
	}
	
	public DataStore(File directory, String dataFile, List<Fun.Tuple2<String,T>>inputData) {
		
		if(!directory.exists())
			directory.mkdirs();
		
		try {
			Logger.info(directory.getCanonicalPath());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		db = DBMaker.newFileDB(new File(directory, dataFile + ".db"))
			.transactionDisable()
			.closeOnJvmShutdown()
	        .make();
        
		Comparator<Tuple2<String, T>> comparator = new Comparator<Fun.Tuple2<String,T>>(){

			@Override
			public int compare(Tuple2<String, T> o1,
					Tuple2<String, T> o2) {
				return o1.a.compareTo(o2.a);
			}
		};

		// need to reverse sort list
		Iterator<Fun.Tuple2<String,T>> iter = Pump.sort(inputData.iterator(),
                true, 100000,
                Collections.reverseOrder(comparator), //reverse  order comparator
                db.getDefaultSerializer()
                );
		
		
		BTreeKeySerializer<String> keySerializer = BTreeKeySerializer.STRING;
		
		map = db.createTreeMap(dataFile)
        	.pumpSource(iter)
        	.pumpPresort(100000) 
        	.keySerializer(keySerializer)
        	.make();
		
		// close/flush db 
		db.close();
		
		// re-connect with transactions enabled
		db = DBMaker.newFileDB(new File(directory, dataFile + ".db"))
				.closeOnJvmShutdown()
		        .make();
		
		map = db.getTreeMap(dataFile);
	}
	
	public void save(String id, T obj) {
		map.put(id, obj);
		db.commit();
	}
	
	public void saveWithoutCommit(String id, T obj) {
		map.put(id, obj);
	}
	
	public void commit() {
		db.commit();
	}
	
	public void delete(String id) {
		map.remove(id);
		db.commit();
	}
	
	public T getById(String id) {
		return map.get(id); 
	}
	
	public Collection<T> getAll() {
		return map.values();
	}
	
	public Integer size() {
		return map.keySet().size();
	}
	
	public boolean contains (String id) {
		return map.containsKey(id);
	}
	
}

@@ -1675,351 +1675,8 @@
 %22))%0A
-%09%09%09// make it fast, we need this so we don't have queues backing up during multipoint jobs%0A%09%09    // note that on a 32 bit machine this will fall back to random access files%0A%09%09%09// and the writes will be slow, mailboxes may back up, OOME's may occur, etc.%0A%09%09    // on a 32bit machine, proceed at your own risk.%0A%09%09%09//.mmapFileEnableIfSupported()%0A
 %09%09%09.

remove spurious comment.