
/*
 * This file injects methods into the BrowserHost object that accept 
 * JavaScript Objects as parameters and calls the related method that
 * accepts JSON strings.
 *
 * This file depends on the BrowserHost and JSON objects having already
 * been injected.
 */

window.BrowserHost = function() {
	wrappedHost = {};
	
	function NO_ARG_TYPE(){};
	function ONE_OBJECT_ARG_TYPE(){};
	function ONE_STRING_ARG_TYPE(){};
    function THREE_STRING_ARG_TYPE(){};
    function ONE_BOOLEAN_OPTIONAL_ARG_TYPE(){};
	
	var proxiedMethods = {"checkTODO": new ONE_OBJECT_ARG_TYPE(),
                        "downloadAfterSMD": new ONE_OBJECT_ARG_TYPE(),
                        "downloadBookWithBookData": new ONE_OBJECT_ARG_TYPE(),
                        "downloadAndOpenBookWithBookData": new ONE_OBJECT_ARG_TYPE(),
                        "openBook": new ONE_OBJECT_ARG_TYPE(),
                        "bookStatus": new ONE_OBJECT_ARG_TYPE(),
                        "canDownloadBook": new ONE_OBJECT_ARG_TYPE(),
                        "reportMetrics": new ONE_OBJECT_ARG_TYPE(),
                        "reportMetricsFromTYP": new NO_ARG_TYPE(),
                        "openInExternalBrowser": new ONE_STRING_ARG_TYPE(),
                        "pageReady": new ONE_BOOLEAN_OPTIONAL_ARG_TYPE(),
                        "closeStore": new NO_ARG_TYPE(),
                        "goToLauncher": new NO_ARG_TYPE(),
                        "toggleForward": new ONE_STRING_ARG_TYPE(),
                        "toggleMenu": new ONE_STRING_ARG_TYPE(),
                        "closeAndGoto": new ONE_STRING_ARG_TYPE(),
                        "dismissKeyboard": new NO_ARG_TYPE(),
                        "onStoreFullyLoaded": new NO_ARG_TYPE(),
                        "openArticle": new ONE_OBJECT_ARG_TYPE(),
                        "triggerNativeTokenPurchaseBottomsheet": new ONE_OBJECT_ARG_TYPE(),
                        "canOpenBookWithOneTap": new NO_ARG_TYPE(),
                        "actionStart": new ONE_OBJECT_ARG_TYPE(),
                        "actionEnd": new ONE_OBJECT_ARG_TYPE(),
                        "displayNativeBottomSheet": new ONE_OBJECT_ARG_TYPE(),
                        "dismissBottomsheet": new ONE_OBJECT_ARG_TYPE(),
                        "faveComplete": new NO_ARG_TYPE(),
                        "addToLibrary": new NO_ARG_TYPE(),
                        "shareBook": new THREE_STRING_ARG_TYPE(),
                        "getNoteData": new NO_ARG_TYPE(),
                        "syncNoteData": new ONE_STRING_ARG_TYPE(),
                        "getWeblabStateForNoteDataInjection": new NO_ARG_TYPE(),
                        "launchQuickView": new ONE_OBJECT_ARG_TYPE(),
                        "openTeenAccountError": new ONE_OBJECT_ARG_TYPE(),
                        "triggerQvWeblab": new NO_ARG_TYPE(),
                        "fetchInAppPurchaseProductInfo": new ONE_OBJECT_ARG_TYPE(),
                        "triggerInAppPurchase": new ONE_OBJECT_ARG_TYPE(),
    };

    function invokeMethod(path, params) {
        window.webkit.messageHandlers[path].postMessage(params);
    }

    function generatePrivateBrowserHostProxy(methodName, argType) {
		return function() {
			if (arguments.length === 0)
				if (!(argType instanceof NO_ARG_TYPE) && !(argType instanceof ONE_BOOLEAN_OPTIONAL_ARG_TYPE))
					throw "Call to method that expects arguments with no arguments";
				else
                    invokeMethod(methodName);
			else if (arguments.length === 1)
                if (typeof(arguments[0]) === "boolean")
                    if (!(argType instanceof ONE_BOOLEAN_OPTIONAL_ARG_TYPE))
                        throw "Boolean as an argument to a method that isn't expecting it";
                    else
                        invokeMethod(methodName, !!arguments[0]);
				else if (typeof(arguments[0]) === "object")
					if (!(argType instanceof ONE_OBJECT_ARG_TYPE))
						throw "Object as argument to method that isn't expecting it";
					else
                        invokeMethod(methodName, JSON.stringify(arguments[0]));
				else if (typeof(arguments[0]) === "string")
					if (!(argType instanceof ONE_STRING_ARG_TYPE))
						throw "String as argument to method that isn't expecting it";
					else
                        invokeMethod(methodName, arguments[0]);
				else
					throw "Unsupported type for proxied method call";
            else if (arguments.length === 3)
                if (typeof(arguments[0]) === "string" && typeof(arguments[1]) === "string" && typeof(arguments[2]) === "string")
                    if (!(argType instanceof THREE_STRING_ARG_TYPE))
                        throw "String as argument to method that isn't expecting it";
                    else
                        invokeMethod(methodName, JSON.stringify({arg1: arguments[0],
                                                                 arg2: arguments[1],
                                                                 arg3: arguments[2]}));
                else
                    throw "Unsupported type for proxied method call";
			else
				throw "Unsupported number of arguments to proxied method call";
		}
	}

	if (window.webkit.messageHandlers.openLinkOutInterstitial) {
		proxiedMethods.openLinkOutInterstitial = new ONE_OBJECT_ARG_TYPE();
	}
    
    if (window.webkit.messageHandlers.openWebPageExternal) {
        proxiedMethods.openWebPageExternal = new ONE_OBJECT_ARG_TYPE();
    }
    
    if (window.webkit.messageHandlers.openExternalAccountLink) {
        proxiedMethods.openExternalAccountLink = new ONE_OBJECT_ARG_TYPE();
    }

    if (window.webkit.messageHandlers.checkExternalLinkAccountEligibility) {
        wrappedHost.checkExternalLinkAccountEligibility = function(payload) {
            var messageData = payload ? JSON.stringify(payload) : "{}";
            return window.webkit.messageHandlers.checkExternalLinkAccountEligibility.postMessage(messageData);
        };
    }


	for (var methodName in proxiedMethods) {
		wrappedHost[methodName] = generatePrivateBrowserHostProxy(methodName,proxiedMethods[methodName]);
	}
	
    wrappedHost.nativeBackClicked = function() {wrappedHost.onBackClicked();};
    
    wrappedHost.nativeMenuClicked = function() {wrappedHost.onMenuClicked();};
    
    wrappedHost.nativeForwardClicked = function() {wrappedHost.onForwardClicked();};	
	
	return wrappedHost;
}();
