/*
 * 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 || WI.TargetType.all;
        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

        // Ask `WI.sharedApp` (if it exists) as it may have a different debuggable type if extra
        // domains were activated, which is the only other time this will be called.
        let currentDebuggableType = WI.sharedApp?.debuggableType || InspectorFrontendHost.debuggableInfo.debuggableType;

        if (debuggableTypes && !debuggableTypes.includes(currentDebuggableType))
            return;

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

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

        let supportedTargetTypes = WI.DebuggableType.supportedTargetTypes(currentDebuggableType);

        for (let [targetType, command] of domain._supportedCommandsForTargetType) {
            if (!supportedTargetTypes.has(targetType))
                continue;

            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 [targetType, event] of domain._supportedEventsForTargetType) {
            if (!supportedTargetTypes.has(targetType))
                continue;

            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(WI.TargetType.all.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 || WI.TargetType.all;
        for (let type of targetTypes)
            this._supportedCommandsForTargetType.add(type, command);
    }

    _addEvent(targetTypes, event)
    {
        targetTypes = targetTypes || WI.TargetType.all;
        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);
    }
};
