package org.hive2hive.core.network;

import java.security.PublicKey;
import java.util.Map;
import java.util.NavigableMap;

import net.tomp2p.dht.StorageLayer;
import net.tomp2p.dht.StorageMemory;
import net.tomp2p.peers.Number640;
import net.tomp2p.rpc.DigestInfo;
import net.tomp2p.storage.Data;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Allows to deny data and/or return manipulated data. <b>Important:</b> This features are used only for
 * testing purposes.
 *
 * @author Seppi, Nico
 */
public class H2HStorageMemory extends StorageLayer {

	private static final Logger logger = LoggerFactory.getLogger(H2HStorageMemory.class);

	public enum StorageMemoryPutMode {
		/** the normal behavior, where each 'put' is checked for version conflicts */
		STANDARD,

		/** Every request to store will fail and returns a {@link net.tomp2p.dht.StorageLayer.PutStatus#FAILED} */
		DENY_ALL
	}

	public enum StorageMemoryGetMode {
		/** the get normal behavior */
		STANDARD,

		/** returns a given value */
		MANIPULATED
	}

	private NavigableMap<Number640, Data> manipulatedMap;

	private StorageMemoryPutMode putMode;
	private StorageMemoryGetMode getMode;

	public H2HStorageMemory() {
		super(new StorageMemory());
		this.putMode = StorageMemoryPutMode.STANDARD;
		this.getMode = StorageMemoryGetMode.STANDARD;
	}

	public void setPutMode(StorageMemoryPutMode mode) {
		assert mode != null;
		this.putMode = mode;
	}

	public void setGetMode(StorageMemoryGetMode mode) {
		assert mode != null;
		this.getMode = mode;
	}

	public void setManipulatedMap(NavigableMap<Number640, Data> manipulatedMap) {
		this.manipulatedMap = manipulatedMap;
	}

	@Override
	public Enum<?> put(Number640 key, Data newData, PublicKey publicKey, boolean putIfAbsent, boolean domainProtection,
			boolean sendSelf) {
		switch (putMode) {
			case STANDARD: {
				return super.put(key, newData, publicKey, putIfAbsent, domainProtection, sendSelf);
			}
			case DENY_ALL: {
				// logger.warn("Memory mode is denying the put request.");
				return PutStatus.FAILED;
			}
			default: {
				logger.error("Invalid mode {}. Returning a failure.", putMode);
				return PutStatus.FAILED;
			}
		}
	}

	public NavigableMap<Number640, Data> getLatestVersion(Number640 key) {
		switch (getMode) {
			case STANDARD: {
				return super.getLatestVersion(key);
			}
			case MANIPULATED: {
				return manipulatedMap;
			}
			default: {
				logger.error("Invalid mode {}. Returning null.", getMode);
				return null;
			}
		}
	}

	@Override
	public DigestInfo digest(Number640 from, Number640 to, int limit, boolean ascending) {
		switch (getMode) {
			case STANDARD: {
				return super.digest(from, to, limit, ascending);
			}
			case MANIPULATED: {
				DigestInfo digestInfo = new DigestInfo();
				for (Map.Entry<Number640, Data> entry : manipulatedMap.entrySet()) {
					digestInfo.put(entry.getKey(), entry.getValue().basedOnSet());
				}
				return digestInfo;
			}
			default: {
				logger.error("Invalid mode {}. Returning null.", getMode);
				return null;
			}
		}
	}

}

@@ -62,16 +62,42 @@
 licKey;%0A
+import java.util.HashMap;%0A
 import j
@@ -140,16 +140,38 @@
 ableMap;
+%0Aimport java.util.Set;
 %0A%0Aimport
@@ -529,16 +529,17 @@
 oses.%0A *
+ 
 %0A * @aut
@@ -2229,24 +2229,885 @@
 %09%09%7D%0A%09%09%7D%0A%09%7D%0A%0A
+%09@Override%0A%09public Map%3CNumber640, Enum%3C?%3E%3E putAll(NavigableMap%3CNumber640, Data%3E dataMap, PublicKey publicKey, boolean putIfAbsent,%0A%09%09%09boolean domainProtection, boolean sendSelf) %7B%0A%09%09switch (putMode) %7B%0A%09%09%09case STANDARD: %7B%0A%09%09%09%09return super.putAll(dataMap, publicKey, putIfAbsent, domainProtection, sendSelf);%0A%09%09%09%7D%0A%09%09%09case DENY_ALL: %7B%0A%09%09%09%09// logger.warn(%22Memory mode is denying the put request.%22);%0A%09%09%09%09return buildReturnMap(dataMap.keySet(), PutStatus.FAILED);%0A%09%09%09%7D%0A%09%09%09default: %7B%0A%09%09%09%09logger.error(%22Invalid mode %7B%7D. Returning a failure.%22, putMode);%0A%09%09%09%09return buildReturnMap(dataMap.keySet(), PutStatus.FAILED);%0A%09%09%09%7D%0A%09%09%7D%0A%09%7D%0A%0A%09private Map%3CNumber640, Enum%3C?%3E%3E buildReturnMap(Set%3CNumber640%3E keys, PutStatus status) %7B%0A%09%09HashMap%3CNumber640, Enum%3C?%3E%3E result = new HashMap%3C%3E(keys.size());%0A%09%09for (Number640 key : keys) %7B%0A%09%09%09result.put(key, status);%0A%09%09%7D%0A%09%09return result;%0A%09%7D%0A%0A
 %09public Navi

Fix storageMemory (override necessary method)