package com.shin1ogawa.servicemock;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

import com.google.appengine.tools.development.ApiProxyLocal;
import com.google.appengine.tools.development.ApiProxyLocalImpl;
import com.google.appengine.tools.development.LocalRpcService;
import com.google.apphosting.api.ApiProxy.ApiProxyException;
import com.google.apphosting.api.ApiProxy.Environment;
import com.google.apphosting.api.ApiProxy.LogRecord;

/**
 * テスト時に使用する{@link ApiProxyLocal}の実装クラス。
 * 
 * @author shin1ogawa
 */
public class ApiProxyLocalMock implements ApiProxyLocal {

	private final ApiProxyLocal delegate;

	private final Map<String, ServiceMock> serviceMocks = new HashMap<String, ServiceMock>(
			5);

	public ApiProxyLocalMock(File appDir) {
		delegate = new ApiProxyLocalImpl(appDir) {
		};
	}

	/**
	 * 各種サービスのMockを登録する。
	 * 
	 * @param serviceMock
	 * @return 登録したserviceMock
	 * @see Map#put(Object, Object)
	 */
	public ServiceMock addServiceMock(ServiceMock serviceMock) {
		return serviceMocks.put(serviceMock.getPackage(), serviceMock);
	}

	/**
	 * 各種サービスのMockを削除する。
	 * 
	 * @param serviceMock
	 * @return 削除対象になったserviceMock
	 * @see Map#remove(Object)
	 */
	public ServiceMock removeServiceMock(ServiceMock serviceMock) {
		return serviceMocks.remove(serviceMock.getPackage());
	}

	public LocalRpcService getService(String serviceName) {
		if (serviceMocks.containsKey(serviceName)) {
			return serviceMocks.get(serviceName);
		}
		return delegate.getService(serviceName);
	}

	public void setProperties(Map<String, String> arg0) {
		delegate.setProperties(arg0);
	}

	public void setProperty(String arg0, String arg1) {
		delegate.setProperty(arg0, arg1);
	}

	public void stop() {
		delegate.stop();
	}

	@SuppressWarnings("unchecked")
	public void log(Environment arg0, LogRecord arg1) {
		delegate.log(arg0, arg1);
	}

	@SuppressWarnings("unchecked")
	public byte[] makeSyncCall(Environment environment, String packageName,
			String methodName, byte[] requestBytes) throws ApiProxyException {
		ServiceMock serviceMock = serviceMocks.get(packageName);
		if (serviceMock != null) {
			return serviceMock.makeSyncCall(environment, packageName,
					methodName, requestBytes);
		}
		return delegate.makeSyncCall(environment, packageName, methodName,
				requestBytes);
	}
}
