/*
 * Copyright (C) 2011 Google Inc. All rights reserved.
 * Copyright (C) 2013, 2015, 2016 Apple Inc. All rights reserved.
 * Copyright (C) 2014 University of Washington.
 *
 * 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.
 */

InspectorBackendClass = class InspectorBackendClass
{
    constructor()
    {
        this._registeredDomains = {};
        this._activeDomains = {};

        this._customTracer = null;
        this._defaultTracer = new WI.LoggingProtocolTracer;
        this._activeTracers = [this._defaultTracer];

        this._supportedDomainsForTargetType = new Multimap;
        this._supportedCommandParameters = new Map;
        this._supportedEventParameters = new Map;

        WI.settings.protocolAutoLogMessages.addEventListener(WI.Setting.Event.Changed, this._startOrStopAutomaticTracing, this);
        WI.settings.protocolAutoLogTimeStats.addEventListener(WI.Setting.Event.Changed, this._startOrStopAutomaticTracing, this);
        this._startOrStopAutomaticTracing();

        this.currentDispatchState = {
            event: null,
            request: null,
            response: null,
        };
    }

    // Public

    // This should only be used for getting enum values (`InspectorBackend.Enum.Domain.Type.Item`).
    // Domain/Command/Event feature checking should use one of the `has*` functions below.
    get Enum()
    {
        return this._activeDomains;
    }

    // It's still possible to set this flag on InspectorBackend to just
    // dump protocol traffic as it happens. For more complex uses of
    // protocol data, install a subclass of WI.ProtocolTracer.
    set dumpInspectorProtocolMessages(value)
    {
        // Implicitly cause automatic logging to start if it's allowed.
        WI.settings.protocolAutoLogMessages.value = value;

        this._defaultTracer.dumpMessagesToConsole = value;
    }

    get dumpInspectorProtocolMessages()
    {
        return WI.settings.protocolAutoLogMessages.value;
    }

    set dumpInspectorTimeStats(value)
    {
        WI.settings.protocolAutoLogTimeStats.value = value;

        if (!this.dumpInspectorProtocolMessages)
            this.dumpInspectorProtocolMessages = true;

        this._defaultTracer.dumpTimingDataToConsole = value;
    }

    get dumpInspectorTimeStats()
    {
        return WI.settings.protocolAutoLogTimeStats.value;
    }

    set filterMultiplexingBackendInspectorProtocolMessages(value)
    {
        WI.settings.protocolFilterMultiplexingBackendMessages.value = value;

        this._defaultTracer.filterMultiplexingBackend = value;
    }

    get filterMultiplexingBackendInspectorProtocolMessages()
    {
        return WI.settings.protocolFilterMultiplexingBackendMessages.value;
    }

    set customTracer(tracer)
    {
        console.assert(!tracer || tracer instanceof WI.ProtocolTracer, tracer);
        console.assert(!tracer || tracer !== this._defaultTracer, tracer);

        // Bail early if no state change is to be made.
        if (!tracer && !this._customTracer)
            return;

        if (tracer === this._customTracer)
            return;

        if (tracer === this._defaultTracer)
            return;

        if (this._customTracer)
            this._customTracer.logFinished();

        this._customTracer = tracer;
        this._activeTracers = [this._defaultTracer];

        if (this._customTracer) {
            this._customTracer.logStarted();
            this._activeTracers.push(this._customTracer);
        }
    }

    get activeTracers()
    {
        return this._activeTracers;
    }

    registerDomain(domainName, targetTypes)
    {
        targetTypes = targetTypes || Object.values(WI.TargetType);
        for (let targetType of targetTypes)
            this._supportedDomainsForTargetType.add(targetType, domainName);

        this._registeredDomains[domainName] = new InspectorBackend.Domain(domainName);
    }

    registerVersion(domainName, version)
    {
        let domain = this._registeredDomains[domainName];
        domain.VERSION = version;
    }

    registerEnum(qualifiedName, enumValues)
    {
        let [domainName, enumName] = qualifiedName.split(".");
        let domain = this._registeredDomains[domainName];
        domain._addEnum(enumName, enumValues);
    }

    registerCommand(qualifiedName, targetTypes, callSignature, replySignature)
    {
        let [domainName, commandName] = qualifiedName.split(".");
        let domain = this._registeredDomains[domainName];
        domain._addCommand(targetTypes, new InspectorBackend.Command(qualifiedName, commandName, callSignature, replySignature));
    }

    registerEvent(qualifiedName, targetTypes, signature)
    {
        let [domainName, eventName] = qualifiedName.split(".");
        let domain = this._registeredDomains[domainName];
        domain._addEvent(targetTypes, new InspectorBackend.Event(qualifiedName, eventName, signature));
    }

    registerDispatcher(domainName, dispatcher)
    {
        let domain = this._registeredDomains[domainName];
        domain._addDispatcher(dispatcher);
    }

    activateDomain(domainName, debuggableTypes)
    {
        // FIXME: <https://webkit.org/b/201150> Web Inspector: remove "extra domains" concept now that domains can be added based on the debuggable type

        if (debuggableTypes && !debuggableTypes.includes(InspectorFrontendHost.debuggableInfo.debuggableType))
            return;

        console.assert(domainName in this._registeredDomains);
        console.assert(!(domainName in this._activeDomains));

        let domain = this._registeredDomains[domainName];
        this._activeDomains[domainName] = domain;

        for (let command of domain._supportedCommandsForTargetType.values()) {
            let parameters = this._supportedCommandParameters.get(command._qualifiedName);
            if (!parameters) {
                parameters = new Set;
                this._supportedCommandParameters.set(command._qualifiedName, parameters);
            }
            parameters.addAll(command._callSignature.map((item) => item.name));
        }

        for (let event of domain._supportedEventsForTargetType.values()) {
            let parameters = this._supportedEventParameters.get(event._qualifiedName);
            if (!parameters) {
                parameters = new Set;
                this._supportedEventParameters.set(event._qualifiedName, parameters);
            }
            parameters.addAll(event._parameterNames);
        }
    }

    dispatch(message)
    {
        InspectorBackend.backendConnection.dispatch(message);
    }

    runAfterPendingDispatches(callback)
    {
        if (!WI.mainTarget) {
            callback();
            return;
        }

        // FIXME: Should this respect pending dispatches in all connections?
        WI.mainTarget.connection.runAfterPendingDispatches(callback);
    }

    supportedDomainsForTargetType(type)
    {
        console.assert(Object.values(WI.TargetType).includes(type), "Unknown target type", type);

        return this._supportedDomainsForTargetType.get(type) || new Set;
    }

    hasDomain(domainName)
    {
        console.assert(!domainName.includes(".") && !domainName.endsWith("Agent"));

        return domainName in this._activeDomains;
    }

    hasCommand(qualifiedName, parameterName)
    {
        console.assert(qualifiedName.includes(".") && !qualifiedName.includes("Agent."));

        let parameters = this._supportedCommandParameters.get(qualifiedName);
        if (!parameters)
            return false;

        return parameterName === undefined || parameters.has(parameterName);
    }

    hasEvent(qualifiedName, parameterName)
    {
        console.assert(qualifiedName.includes(".") && !qualifiedName.includes("Agent."));

        let parameters = this._supportedEventParameters.get(qualifiedName);
        if (!parameters)
            return false;

        return parameterName === undefined || parameters.has(parameterName);
    }

    getVersion(domainName)
    {
        console.assert(!domainName.includes(".") && !domainName.endsWith("Agent"));

        let domain = this._activeDomains[domainName];
        if (domain && "VERSION" in domain)
            return domain.VERSION;

        return -Infinity;
    }

    invokeCommand(qualifiedName, targetType, connection, commandArguments, callback)
    {
        let [domainName, commandName] = qualifiedName.split(".");

        let domain = this._activeDomains[domainName];
        return domain._invokeCommand(commandName, targetType, connection, commandArguments, callback);
    }

    // Private

    _makeAgent(domainName, target)
    {
        let domain = this._activeDomains[domainName];
        return domain._makeAgent(target);
    }

    _startOrStopAutomaticTracing()
    {
        this._defaultTracer.dumpMessagesToConsole = this.dumpInspectorProtocolMessages;
        this._defaultTracer.dumpTimingDataToConsole = this.dumpTimingDataToConsole;
        this._defaultTracer.filterMultiplexingBackend = this.filterMultiplexingBackendInspectorProtocolMessages;
    }
};

InspectorBackend = new InspectorBackendClass;

InspectorBackend.Domain = class InspectorBackendDomain
{
    constructor(domainName)
    {
        this._domainName = domainName;

        // Enums are stored directly on the Domain instance using their unqualified
        // type name as the property. Thus, callers can write: Domain.EnumType.

        this._dispatcher = null;

        this._supportedCommandsForTargetType = new Multimap;
        this._supportedEventsForTargetType = new Multimap;
    }

    // Private

    _addEnum(enumName, enumValues)
    {
        console.assert(!(enumName in this));
        this[enumName] = enumValues;
    }

    _addCommand(targetTypes, command)
    {
        targetTypes = targetTypes || Object.values(WI.TargetType);
        for (let type of targetTypes)
            this._supportedCommandsForTargetType.add(type, command);
    }

    _addEvent(targetTypes, event)
    {
        targetTypes = targetTypes || Object.values(WI.TargetType);
        for (let type of targetTypes)
            this._supportedEventsForTargetType.add(type, event);
    }

    _addDispatcher(dispatcher)
    {
        console.assert(!this._dispatcher);
        this._dispatcher = dispatcher;
    }

    _makeAgent(target)
    {
        let commands = this._supportedCommandsForTargetType.get(target.type) || new Set;
        let events = this._supportedEventsForTargetType.get(target.type) || new Set;
        return new InspectorBackend.Agent(target, commands, events, this._dispatcher);
    }

    _invokeCommand(commandName, targetType, connection, commandArguments, callback)
    {
        let commands = this._supportedCommandsForTargetType.get(targetType);
        for (let command of commands) {
            if (command._commandName === commandName)
                return command._makeCallable(connection).invoke(commandArguments, callback);
        }

        console.assert();
    }
};

InspectorBackend.Agent = class InspectorBackendAgent
{
    constructor(target, commands, events, dispatcher)
    {
        // Commands are stored directly on the Agent instance using their unqualified
        // method name as the property. Thus, callers can write: DomainAgent.commandName().
        for (let command of commands) {
            this[command._commandName] = command._makeCallable(target.connection);
            target._supportedCommandParameters.set(command._qualifiedName, command);
        }

        this._events = {};
        for (let event of events) {
            this._events[event._eventName] = event;
            target._supportedEventParameters.set(event._qualifiedName, event);
        }

        this._dispatcher = dispatcher ? new dispatcher(target) : null;
    }
};

InspectorBackend.Dispatcher = class InspectorBackendDispatcher
{
    constructor(target)
    {
        console.assert(target instanceof WI.Target);

        this._target = target;
    }
};

InspectorBackend.Command = class InspectorBackendCommand
{
    constructor(qualifiedName, commandName, callSignature, replySignature)
    {
        this._qualifiedName = qualifiedName;
        this._commandName = commandName;
        this._callSignature = callSignature || [];
        this._replySignature = replySignature || [];
    }

    // Private

    _hasParameter(parameterName)
    {
        return this._callSignature.some((item) => item.name === parameterName);
    }

    _makeCallable(connection)
    {
        let instance = new InspectorBackend.Callable(this, connection);

        function callable() {
            console.assert(this instanceof InspectorBackend.Agent);
            return instance._invokeWithArguments.call(instance, Array.from(arguments));
        }
        callable._instance = instance;
        Object.setPrototypeOf(callable, InspectorBackend.Callable.prototype);
        return callable;
    }
};

InspectorBackend.Event = class InspectorBackendEvent
{
    constructor(qualifiedName, eventName, parameterNames)
    {
        this._qualifiedName = qualifiedName;
        this._eventName = eventName;
        this._parameterNames = parameterNames || [];
    }

    // Private

    _hasParameter(parameterName)
    {
        return this._parameterNames.includes(parameterName);
    }
};

// InspectorBackend.Callable can't use ES6 classes because of its trampoline nature.
// But we can use strict mode to get stricter handling of the code inside its functions.
InspectorBackend.Callable = function(command, connection)
{
    "use strict";

    this._command = command;
    this._connection = connection;

    this._instance = this;
};

// As part of the workaround to make commands callable, these functions use `this._instance`.
// `this` could refer to the callable trampoline, or the InspectorBackend.Callable instance.
InspectorBackend.Callable.prototype = {
    __proto__: Function.prototype,

    // Public

    invoke(commandArguments, callback)
    {
        "use strict";

        let command = this._instance._command;
        let connection = this._instance._connection;

        function deliverFailure(message) {
            console.error(`Protocol Error: ${message}`);
            if (callback)
                setTimeout(callback.bind(null, message), 0);
            else
                return Promise.reject(new Error(message));
        }

        if (typeof commandArguments !== "object")
            return deliverFailure(`invoke expects an object for command arguments but its type is '${typeof commandArguments}'.`);

        let parameters = {};
        for (let {name, type, optional} of command._callSignature) {
            if (!(name in commandArguments) && !optional)
                return deliverFailure(`Missing argument '${name}' for command '${command._qualifiedName}'.`);

            let value = commandArguments[name];
            if (optional && value === undefined)
                continue;

            if (typeof value !== type)
                return deliverFailure(`Invalid type of argument '${name}' for command '${command._qualifiedName}' call. It must be '${type}' but it is '${typeof value}'.`);

            parameters[name] = value;
        }

        if (typeof callback === "function")
            connection._sendCommandToBackendWithCallback(command, parameters, callback);
        else
            return connection._sendCommandToBackendExpectingPromise(command, parameters);
    },

    // Private

    _invokeWithArguments(commandArguments)
    {
        "use strict";

        let command = this._instance._command;
        let connection = this._instance._connection;
        let callback = typeof commandArguments.lastValue === "function" ? commandArguments.pop() : null;

        function deliverFailure(message) {
            console.error(`Protocol Error: ${message}`);
            if (callback)
                setTimeout(callback.bind(null, message), 0);
            else
                return Promise.reject(new Error(message));
        }

        let parameters = {};
        for (let {name, type, optional} of command._callSignature) {
            if (!commandArguments.length && !optional)
                return deliverFailure(`Invalid number of arguments for command '${command._qualifiedName}'.`);

            let value = commandArguments.shift();
            if (optional && value === undefined)
                continue;

            if (typeof value !== type)
                return deliverFailure(`Invalid type of argument '${name}' for command '${command._qualifiedName}' call. It must be '${type}' but it is '${typeof value}'.`);

            parameters[name] = value;
        }

        if (!callback && commandArguments.length === 1 && commandArguments[0] !== undefined)
            return deliverFailure(`Protocol Error: Optional callback argument for command '${command._qualifiedName}' call must be a function but its type is '${typeof commandArguments[0]}'.`);

        if (callback)
            connection._sendCommandToBackendWithCallback(command, parameters, callback);
        else
            return connection._sendCommandToBackendExpectingPromise(command, parameters);
    }
};
