/*
 * 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.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);
    }
};
