/*
 * Copyright (C) 2013, 2015 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.ButtonNavigationItem = class ButtonNavigationItem extends WI.NavigationItem
{
    constructor(identifier, toolTipOrLabel, image, imageWidth, imageHeight, role, label)
    {
        role = role || "button";
        super(identifier, role);

        console.assert(identifier);
        console.assert(toolTipOrLabel);

        this._enabled = true;

        this.element.addEventListener("click", this._mouseClicked.bind(this));

        // Don't move the focus on the button when clicking on it. This matches macOS behavior.
        this.element.addEventListener("mousedown", this._handleMouseDown.bind(this), true);

        this._role = role;
        if (this._role === "button")
            this.element.addEventListener("keydown", this._handleKeyDown.bind(this));

        if (label)
            this.element.setAttribute("aria-label", label);

        this._buttonStyle = null;
        this._disabled = false;
        this._image = image || null;
        this._imageWidth = imageWidth || 16;
        this._imageHeight = imageHeight || 16;
        this._label = toolTipOrLabel;

        this._updateTabIndex();

        this.buttonStyle = this._image ? WI.ButtonNavigationItem.Style.Image : WI.ButtonNavigationItem.Style.Text;

        this.imageType = this._image ? WI.ButtonNavigationItem.ImageType.SVG : null;

        if (this.buttonStyle === WI.ButtonNavigationItem.Style.Image)
            this.tooltip = toolTipOrLabel;
    }

    // Public

    get label()
    {
        return this._label;
    }

    set label(newLabel)
    {
        newLabel = newLabel || "";
        if (this._label === newLabel)
            return;

        this._label = newLabel;
        this._update();

        if (this.parentNavigationBar)
            this.parentNavigationBar.needsLayout();
    }

    get image()
    {
        return this._image;
    }

    set image(newImage)
    {
        newImage = newImage || null;
        if (this._image === newImage)
            return;

        this._image = newImage;
        this._update();
    }

    get enabled()
    {
        return this._enabled;
    }

    set enabled(flag)
    {
        flag = !!flag;
        if (this._enabled === flag)
            return;

        this._enabled = flag;
        this.element.classList.toggle("disabled", !this._enabled);
        this.element.ariaDisabled = !this._enabled;

        this._updateTabIndex();
    }

    get buttonStyle()
    {
        return this._buttonStyle;
    }

    set buttonStyle(newButtonStyle)
    {
        newButtonStyle = newButtonStyle || WI.ButtonNavigationItem.Style.Image;
        if (this._buttonStyle === newButtonStyle)
            return;

        this.element.classList.remove(...Object.values(WI.ButtonNavigationItem.Style));
        this.element.classList.add(newButtonStyle);

        this._buttonStyle = newButtonStyle;
        this._update();

        if (this.parentNavigationBar)
            this.parentNavigationBar.needsLayout();
    }

    get imageType()
    {
        return this._imageType;
    }

    set imageType(imageType)
    {
        console.assert(!imageType || Object.values(WI.ButtonNavigationItem.ImageType).includes(imageType), imageType);
        console.assert(!imageType || (this._buttonStyle === WI.ButtonNavigationItem.Style.Image || this._buttonStyle === WI.ButtonNavigationItem.Style.ImageAndText));

        if (this._imageType === imageType)
            return;

        this._imageType = imageType;

        this._update();

        if (this.parentNavigationBar)
            this.parentNavigationBar.needsLayout();
    }

    // Protected

    get totalMargin()
    {
        let totalMargin = super.totalMargin;
        if (this._buttonStyle === ButtonNavigationItem.Style.Text)
            return totalMargin + 4; /* .navigation-bar .item.button.text-only */
        return totalMargin;
    }

    get additionalClassNames()
    {
        return ["button"];
    }

    get tabbable()
    {
        return this._role === "button";
    }

    // Private

    _mouseClicked(event)
    {
        this._buttonPressed(event);
    }

    _handleMouseDown(event)
    {
        // Clicking on a button should NOT focus on it.
        event.preventDefault();
    }

    _handleKeyDown(event)
    {
        if (event.code === "Enter" || event.code === "Space") {
            event.stop();
            this._buttonPressed(event);
        }
    }

    _buttonPressed(event)
    {
        if (!this.enabled)
            return;
        this.dispatchEventToListeners(WI.ButtonNavigationItem.Event.Clicked, {nativeEvent: event});
    }

    _update()
    {
        this.element.removeChildren();

        if (this._buttonStyle === WI.ButtonNavigationItem.Style.Text)
            this.element.textContent = this._label;
        else {
            switch (this._imageType) {
            case null:
            case WI.ButtonNavigationItem.ImageType.SVG: {
                let glyphElement = WI.ImageUtilities.useSVGSymbol(this._image, "glyph");
                glyphElement.style.width = this._imageWidth + "px";
                glyphElement.style.height = this._imageHeight + "px";
                this.element.appendChild(glyphElement);
                break;
            }

            case WI.ButtonNavigationItem.ImageType.IMG: {
                let img = this.element.appendChild(document.createElement("img"));
                img.src = this._image;
                break;
            }
            }

            if (this._buttonStyle === WI.ButtonNavigationItem.Style.ImageAndText) {
                let labelElement = this.element.appendChild(document.createElement("span"));
                labelElement.textContent = this._label;
            }
        }
    }

    _updateTabIndex()
    {
        if (!this._enabled) {
            this.element.tabIndex = -1;
            return;
        }

        this.element.tabIndex = this.tabbable ? 0 : -1;
    }
};

WI.ButtonNavigationItem.Event = {
    Clicked: "button-navigation-item-clicked"
};

WI.ButtonNavigationItem.Style = {
    Image: "image-only",
    Text: "text-only",
    ImageAndText: "image-and-text",
};

WI.ButtonNavigationItem.ImageType = {
    SVG: "image-type-svg",
    IMG: "image-type-img",
};
