/*
 * Copyright (C) 2021 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:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
 */

WI.CSSPropertyNameCompletions = class CSSPropertyNameCompletions extends WI.CSSCompletions
{
    constructor(properties, options = {})
    {
        console.assert(Array.isArray(properties), properties);
        console.assert(properties[0].name, "Expected an array of objects with `name` key", properties);

        let values = [];
        for (let property of properties) {
            console.assert(property.name);

            values.push(property.name);
            if (Array.isArray(property.aliases))
                values.pushAll(property.aliases);
        }

        super(values, options);

        this._cachedSortedPropertyNames = this.values.slice();
        this._needsVariablesFromInspectedNode = true;

        WI.domManager.addEventListener(WI.DOMManager.Event.InspectedNodeChanged, this._handleInspectedNodeChanged, this);
    }

    // Public

    isValidPropertyName(name)
    {
        return this.values.includes(name);
    }

    executeQuery(query)
    {
        this._updateValuesWithLatestCSSVariablesIfNeeded();

        return super.executeQuery(query);
    }

    startsWith(prefix)
    {
        this._updateValuesWithLatestCSSVariablesIfNeeded();

        return super.startsWith(prefix);
    }

    addValues()
    {
        console.assert(false, "Adding values will overwrite the list of supported CSS property names.");
    }

    // Private

    _updateValuesWithLatestCSSVariablesIfNeeded()
    {
        if (!this._needsVariablesFromInspectedNode)
            return;

        // An inspected node is not guaranteed to exist when unit testing.
        if (!WI.domManager.inspectedNode) {
            this._needsVariablesFromInspectedNode = false;
            return;
        }

        let values = Array.from(WI.cssManager.stylesForNode(WI.domManager.inspectedNode).allCSSVariables);
        values.pushAll(this._cachedSortedPropertyNames);
        this.replaceValues(values);

        this._needsVariablesFromInspectedNode = false;
    }

    _handleInspectedNodeChanged(event)
    {
        this._needsVariablesFromInspectedNode = true;

        if (event.data.lastInspectedNode)
            WI.cssManager.stylesForNode(event.data.lastInspectedNode).removeEventListener(WI.DOMNodeStyles.Event.NeedsRefresh, this._handleNodesStylesNeedsRefresh, this);

        WI.cssManager.stylesForNode(WI.domManager.inspectedNode).addEventListener(WI.DOMNodeStyles.Event.NeedsRefresh, this._handleNodesStylesNeedsRefresh, this);
    }

    _handleNodesStylesNeedsRefresh(event)
    {
        this._needsVariablesFromInspectedNode = true;
    }
};
