/*
 * Copyright (C) 2011 Google Inc. All rights reserved.
 * Copyright (C) 2013 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @constructor
 */
function InspectorBackendClass()
{
    this._lastCallbackId = 1;
    this._pendingResponsesCount = 0;
    this._callbacks = {};
    this._domainDispatchers = {};
    this._eventArgs = {};
    this._replyArgs = {};

    this.dumpInspectorTimeStats = false;
    this.dumpInspectorProtocolMessages = false;
    this._initialized = false;
}

InspectorBackendClass.prototype = {
    _wrap: function(callback, method)
    {
        var callbackId = this._lastCallbackId++;
        if (!callback)
            callback = function() {};

        this._callbacks[callbackId] = callback;
        callback.methodName = method;
        if (this.dumpInspectorTimeStats)
            callback.sendRequestTime = Date.now();

        return callbackId;
    },

    _getAgent: function(domain)
    {
        var agentName = domain + "Agent";
        if (!window[agentName])
            window[agentName] = {};
        return window[agentName];
    },

    registerCommand: function(method, signature, replyArgs)
    {
        var domainAndMethod = method.split(".");
        var agent = this._getAgent(domainAndMethod[0]);

        agent[domainAndMethod[1]] = this._sendMessageToBackend.bind(this, method, signature);
        agent[domainAndMethod[1]]["invoke"] = this._invoke.bind(this, method, signature);
        agent[domainAndMethod[1]]["supports"] = this._supports.bind(this, method, signature);
        this._replyArgs[method] = replyArgs;

        this._initialized = true;
    },

    registerEnum: function(type, values)
    {
        var domainAndMethod = type.split(".");
        var agent = this._getAgent(domainAndMethod[0]);

        agent[domainAndMethod[1]] = values;

        this._initialized = true;
    },

    registerEvent: function(eventName, params)
    {
        this._eventArgs[eventName] = params;

        this._initialized = true;
    },

    _invoke: function(method, signature, args, callback)
    {
        this._wrapCallbackAndSendMessageObject(method, args, callback);
    },

    _supports: function(method, signature, paramName)
    {
        for (var i = 0; i < signature.length; ++i) {
            if (signature[i]["name"] === paramName)
                return true;
        }

        return false;
    },

    _sendMessageToBackend: function(method, signature, vararg)
    {
        var args = Array.prototype.slice.call(arguments, 2);
        var callback = typeof args.lastValue === "function" ? args.pop() : null;

        var params = {};
        var hasParams = false;
        for (var i = 0; i < signature.length; ++i) {
            var param = signature[i];
            var paramName = param["name"];
            var typeName = param["type"];
            var optionalFlag = param["optional"];

            if (!args.length && !optionalFlag) {
                console.error("Protocol Error: Invalid number of arguments for method '" + method + "' call. It must have the following arguments '" + JSON.stringify(signature) + "'.");
                return;
            }

            var value = args.shift();
            if (optionalFlag && typeof value === "undefined") {
                continue;
            }

            if (typeof value !== typeName) {
                console.error("Protocol Error: Invalid type of argument '" + paramName + "' for method '" + method + "' call. It must be '" + typeName + "' but it is '" + typeof value + "'.");
                return;
            }

            params[paramName] = value;
            hasParams = true;
        }

        if (args.length === 1 && !callback) {
            if (typeof args[0] !== "undefined") {
                console.error("Protocol Error: Optional callback argument for method '" + method + "' call must be a function but its type is '" + typeof args[0] + "'.");
                return;
            }
        }

        this._wrapCallbackAndSendMessageObject(method, hasParams ? params : null, callback);
    },

    _wrapCallbackAndSendMessageObject: function(method, params, callback)
    {
        var messageObject = {};
        messageObject.method = method;
        if (params)
            messageObject.params = params;
        messageObject.id = this._wrap(callback, method);

        if (this.dumpInspectorProtocolMessages)
            console.log("frontend: " + JSON.stringify(messageObject));

        ++this._pendingResponsesCount;
        this.sendMessageObjectToBackend(messageObject);
    },

    sendMessageObjectToBackend: function(messageObject)
    {
        var message = JSON.stringify(messageObject);
        InspectorFrontendHost.sendMessageToBackend(message);
    },

    registerDomainDispatcher: function(domain, dispatcher)
    {
        this._domainDispatchers[domain] = dispatcher;
    },

    dispatch: function(message)
    {
        if (this.dumpInspectorProtocolMessages)
            console.log("backend: " + ((typeof message === "string") ? message : JSON.stringify(message)));

        var messageObject = (typeof message === "string") ? JSON.parse(message) : message;

        if ("id" in messageObject) { // just a response for some request
            if (messageObject.error) {
                if (messageObject.error.code !== -32000)
                    this.reportProtocolError(messageObject);
            }

            var callback = this._callbacks[messageObject.id];
            if (callback) {
                var argumentsArray = [];
                if (messageObject.result) {
                    if (callback.expectsResultObject) {
                        // The callback expects results as an object with properties, this is useful
                        // for backwards compatibility with renamed or different parameters.
                        argumentsArray.push(messageObject.result);
                    } else {
                        var paramNames = this._replyArgs[callback.methodName];
                        if (paramNames) {
                            for (var i = 0; i < paramNames.length; ++i)
                                argumentsArray.push(messageObject.result[paramNames[i]]);
                        }
                    }
                }

                var processingStartTime;
                if (this.dumpInspectorTimeStats && callback.methodName)
                    processingStartTime = Date.now();

                argumentsArray.unshift(messageObject.error ? messageObject.error.message : null);
                callback.apply(null, argumentsArray);
                --this._pendingResponsesCount;
                delete this._callbacks[messageObject.id];

                if (this.dumpInspectorTimeStats && callback.methodName)
                    console.log("time-stats: " + callback.methodName + " = " + (processingStartTime - callback.sendRequestTime) + " + " + (Date.now() - processingStartTime));
            }

            if (this._scripts && !this._pendingResponsesCount)
                this.runAfterPendingDispatches();

            return;
        } else {
            var method = messageObject.method.split(".");
            var domainName = method[0];
            var functionName = method[1];
            if (!(domainName in this._domainDispatchers)) {
                console.error("Protocol Error: the message is for non-existing domain '" + domainName + "'");
                return;
            }
            var dispatcher = this._domainDispatchers[domainName];
            if (!(functionName in dispatcher)) {
                console.error("Protocol Error: Attempted to dispatch an unimplemented method '" + messageObject.method + "'");
                return;
            }

            if (!this._eventArgs[messageObject.method]) {
                console.error("Protocol Error: Attempted to dispatch an unspecified method '" + messageObject.method + "'");
                return;
            }

            var params = [];
            if (messageObject.params) {
                var paramNames = this._eventArgs[messageObject.method];
                for (var i = 0; i < paramNames.length; ++i)
                    params.push(messageObject.params[paramNames[i]]);
            }

            var processingStartTime;
            if (this.dumpInspectorTimeStats)
                processingStartTime = Date.now();

            dispatcher[functionName].apply(dispatcher, params);

            if (this.dumpInspectorTimeStats)
                console.log("time-stats: " + messageObject.method + " = " + (Date.now() - processingStartTime));
        }
    },

    reportProtocolError: function(messageObject)
    {
        console.error("Request with id = " + messageObject.id + " failed. " + JSON.stringify(messageObject.error));
    },

    /**
     * @param {string=} script
     */
    runAfterPendingDispatches: function(script)
    {
        if (!this._scripts)
            this._scripts = [];

        if (script)
            this._scripts.push(script);

        if (!this._pendingResponsesCount) {
            var scripts = this._scripts;
            this._scripts = [];
            for (var id = 0; id < scripts.length; ++id)
                 scripts[id].call(this);
        }
    }
}

InspectorBackend = new InspectorBackendClass();
