/*
 * 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.NavigationBar = class NavigationBar extends WI.View
{
    constructor(element, {role, sizesToFit, navigationItems} = {})
    {
        super(element);

        this.element.classList.add(this.constructor.StyleClassName || "navigation-bar");

        if (role)
            this.element.setAttribute("role", role);

        this.element.addEventListener("keydown", this._keyDown.bind(this), false);
        this.element.addEventListener("mousedown", this._mouseDown.bind(this), true);

        this._role = role;
        this._sizesToFit = sizesToFit || false;
        this._minimumWidth = NaN;
        this._navigationItems = [];
        this._selectedNavigationItem = null;

        this._mouseMovedEventListener = this._mouseMoved.bind(this);
        this._mouseUpEventListener = this._mouseUp.bind(this);

        if (navigationItems) {
            for (var i = 0; i < navigationItems.length; ++i)
                this.addNavigationItem(navigationItems[i]);
        }
    }

    // Public

    get sizesToFit() { return this._sizesToFit; }

    addNavigationItem(navigationItem, parentElement)
    {
        return this.insertNavigationItem(navigationItem, Infinity, parentElement);
    }

    insertNavigationItem(navigationItem, index, parentElement)
    {
        console.assert(navigationItem instanceof WI.NavigationItem);
        if (!(navigationItem instanceof WI.NavigationItem))
            return null;

        if (navigationItem.parentNavigationBar)
            navigationItem.parentNavigationBar.removeNavigationItem(navigationItem);

        navigationItem.didAttach(this);

        console.assert(!isFinite(index) || (index >= 0 && index <= this._navigationItems.length));
        index = Math.max(0, Math.min(index, this._navigationItems.length));

        this._navigationItems.splice(index, 0, navigationItem);

        if (!parentElement)
            parentElement = this.element;

        var nextSibling = this._navigationItems[index + 1];
        var nextSiblingElement = nextSibling ? nextSibling.element : null;
        if (nextSiblingElement && nextSiblingElement.parentNode !== parentElement)
            nextSiblingElement = null;

        parentElement.insertBefore(navigationItem.element, nextSiblingElement);

        this._minimumWidth = NaN;

        this.needsLayout();

        return navigationItem;
    }

    removeNavigationItem(navigationItem)
    {
        console.assert(navigationItem instanceof WI.NavigationItem);
        if (!(navigationItem instanceof WI.NavigationItem))
            return null;

        if (!navigationItem._parentNavigationBar)
            return null;

        console.assert(navigationItem._parentNavigationBar === this, "Cannot remove item with unexpected parent bar.", navigationItem);
        if (navigationItem._parentNavigationBar !== this)
            return null;

        navigationItem.didDetach();

        if (this._selectedNavigationItem === navigationItem)
            this.selectedNavigationItem = null;

        this._navigationItems.remove(navigationItem);
        navigationItem.element.remove();

        this._minimumWidth = NaN;

        this.needsLayout();

        return navigationItem;
    }

    get selectedNavigationItem()
    {
        return this._selectedNavigationItem;
    }

    set selectedNavigationItem(navigationItem)
    {
        let navigationItemHasOtherParent = navigationItem && navigationItem.parentNavigationBar !== this;
        console.assert(!navigationItemHasOtherParent, "Cannot select item with unexpected parent bar.", navigationItem);
        if (navigationItemHasOtherParent)
            return;

        // Only radio navigation items can be selected.
        if (!(navigationItem instanceof WI.RadioButtonNavigationItem))
            navigationItem = null;

        if (this._selectedNavigationItem === navigationItem)
            return;

        if (this._selectedNavigationItem)
            this._selectedNavigationItem.selected = false;

        this._selectedNavigationItem = navigationItem || null;

        if (this._selectedNavigationItem)
            this._selectedNavigationItem.selected = true;

        // When the mouse is down don't dispatch the selected event, it will be dispatched on mouse up.
        // This prevents sending the event while the user is scrubbing the bar.
        if (!this._mouseIsDown)
            this.dispatchEventToListeners(WI.NavigationBar.Event.NavigationItemSelected);
    }

    get navigationItems()
    {
        return this._navigationItems;
    }

    get minimumWidth()
    {
        if (isNaN(this._minimumWidth))
            this._minimumWidth = this._calculateMinimumWidth();
        return this._minimumWidth;
    }

    findNavigationItem(identifier)
    {
        function matchingSelfOrChild(item) {
            if (item.identifier === identifier)
                return item;

            if (item instanceof WI.GroupNavigationItem) {
                for (let childItem of item.navigationItems) {
                    let result = matchingSelfOrChild(childItem);
                    if (result)
                        return result;
                }
            }

            return null;
        }

        for (let item of this._navigationItems) {
            let result = matchingSelfOrChild(item);
            if (result)
                return result;
        }

        return null;
    }

    layout()
    {
        super.layout();

        this._minimumWidth = NaN;

        // Remove the collapsed style class to test if the items can fit at full width.
        this.element.classList.remove(WI.NavigationBar.CollapsedStyleClassName);

        function forceItemHidden(item, hidden) {
            item[WI.NavigationBar.ForceHiddenSymbol] = hidden;
            item.element.classList.toggle("force-hidden", hidden);
        }

        function isDivider(item) {
            return item instanceof WI.DividerNavigationItem;
        }

        // Tell each navigation item to update to full width if needed.
        for (let item of this._navigationItems) {
            forceItemHidden(item, false);
            item.update({expandOnly: true});
        }

        if (this.sizesToFit)
            return;

        let visibleNavigationItems = this._visibleNavigationItems;

        function calculateVisibleItemWidth() {
            return visibleNavigationItems.reduce((total, item) => total + item.width, 0);
        }

        let totalItemWidth = calculateVisibleItemWidth();

        const barWidth = this.element.realOffsetWidth;

        // Add the collapsed class back if the items are wider than the bar.
        if (totalItemWidth > barWidth)
            this.element.classList.add(WI.NavigationBar.CollapsedStyleClassName);

        // Give each navigation item the opportunity to collapse further.
        for (let item of visibleNavigationItems)
            item.update();

        totalItemWidth = calculateVisibleItemWidth();

        if (totalItemWidth > barWidth) {
            if (this.parentView instanceof WI.Sidebar) {
                this.parentView.width = this.minimumWidth;
                return;
            }

            // Hide visible items, starting with the lowest priority item, until
            // the bar fits the available width.
            visibleNavigationItems.sort((a, b) => a.visibilityPriority - b.visibilityPriority);

            while (totalItemWidth > barWidth && visibleNavigationItems.length) {
                let navigationItem = visibleNavigationItems.shift();
                totalItemWidth -= navigationItem.width;
                forceItemHidden(navigationItem, true);
            }

            visibleNavigationItems = this._visibleNavigationItems;
        }

        // Hide leading, trailing, and consecutive dividers.
        let previousItem = null;
        for (let item of visibleNavigationItems) {
            if (isDivider(item) && (!previousItem || isDivider(previousItem))) {
                forceItemHidden(item);
                continue;
            }

            previousItem = item;
        }

        if (isDivider(previousItem))
            forceItemHidden(previousItem);
    }

    // Private

    _mouseDown(event)
    {
        // Only handle left mouse clicks.
        if (event.button !== 0)
            return;

        var itemElement = event.target.closest("." + WI.RadioButtonNavigationItem.StyleClassName);
        if (!itemElement || !itemElement.navigationItem)
            return;

        if (this._role === "tablist") {
            if (this.element.contains(document.activeElement)) {
                // If clicking on a tab, stop the event from being handled by the button element. Instead,
                // pass focus to the selected tab. Otherwise, let the button become activated normally.
                event.stopPropagation();
            }
        }

        this._previousSelectedNavigationItem = this.selectedNavigationItem;
        this.selectedNavigationItem = itemElement.navigationItem;

        this._mouseIsDown = true;

        if (typeof this.selectedNavigationItem.dontPreventDefaultOnNavigationBarMouseDown === "function"
            && this.selectedNavigationItem.dontPreventDefaultOnNavigationBarMouseDown()
            && this._previousSelectedNavigationItem === this.selectedNavigationItem)
            return;

        // Register these listeners on the document so we can track the mouse if it leaves the navigation bar.
        document.addEventListener("mousemove", this._mouseMovedEventListener, false);
        document.addEventListener("mouseup", this._mouseUpEventListener, false);
    }

    _mouseMoved(event)
    {
        console.assert(event.button === 0);
        console.assert(this._mouseIsDown);
        if (!this._mouseIsDown)
            return;

        event.preventDefault();
        event.stopPropagation();

        var itemElement = event.target.closest("." + WI.RadioButtonNavigationItem.StyleClassName);
        if (!itemElement || !itemElement.navigationItem || !this.element.contains(itemElement)) {
            // Find the element that is at the X position of the mouse, even when the mouse is no longer
            // vertically in the navigation bar.
            var element = document.elementFromPoint(event.pageX, this.element.totalOffsetTop + (this.element.offsetHeight / 2));
            if (!element)
                return;

            itemElement = element.closest("." + WI.RadioButtonNavigationItem.StyleClassName);
            if (!itemElement || !itemElement.navigationItem || !this.element.contains(itemElement))
                return;
        }

        if (this.selectedNavigationItem)
            this.selectedNavigationItem.active = false;

        this.selectedNavigationItem = itemElement.navigationItem;

        this.selectedNavigationItem.active = true;
    }

    _mouseUp(event)
    {
        console.assert(event.button === 0);
        console.assert(this._mouseIsDown);
        if (!this._mouseIsDown)
            return;

        if (this.selectedNavigationItem)
            this.selectedNavigationItem.active = false;

        this._mouseIsDown = false;

        document.removeEventListener("mousemove", this._mouseMovedEventListener, false);
        document.removeEventListener("mouseup", this._mouseUpEventListener, false);

        // Dispatch the selected event here since the selectedNavigationItem setter surpresses it
        // while the mouse is down to prevent sending it while scrubbing the bar.
        if (this._previousSelectedNavigationItem !== this.selectedNavigationItem)
            this.dispatchEventToListeners(WI.NavigationBar.Event.NavigationItemSelected);

        delete this._previousSelectedNavigationItem;

        event.preventDefault();
        event.stopPropagation();
    }

    _keyDown(event)
    {
        let isLeftArrow = event.code === "ArrowLeft";
        if (!isLeftArrow && event.code !== "ArrowRight")
            return;

        if (this._selectedNavigationItem?.element !== document.activeElement)
            return;

        event.preventDefault();
        event.stopPropagation();

        let delta = isLeftArrow ? -1 : 1;
        if (WI.resolveLayoutDirectionForElement(this._element) === WI.LayoutDirection.RTL)
            delta *= -1;

        let selectedIndex = this._navigationItems.indexOf(this._selectedNavigationItem);

        if (selectedIndex === -1)
            selectedIndex = (this._navigationItems.length + delta) % this._navigationItems.length;

        while (true) {
            selectedIndex += delta;

            if (selectedIndex < 0 || selectedIndex >= this._navigationItems.length)
                break;

            let selectedItemCandidate = this._navigationItems[selectedIndex];
            if (selectedItemCandidate instanceof WI.RadioButtonNavigationItem) {
                this.selectedNavigationItem = selectedItemCandidate;
                this.selectedNavigationItem.element.focus();
                break;
            }
        }
    }

    _calculateMinimumWidth()
    {
        let visibleNavigationItems = this._visibleNavigationItems;
        if (!visibleNavigationItems.length)
            return 0;

        const wasCollapsed = this.element.classList.contains(WI.NavigationBar.CollapsedStyleClassName);

        // Add the collapsed style class to calculate the width of the items when they are collapsed.
        if (!wasCollapsed)
            this.element.classList.add(WI.NavigationBar.CollapsedStyleClassName);

        let totalItemWidth = visibleNavigationItems.reduce((total, item) => total + item.minimumWidth, 0);

        // Remove the collapsed style class if we were not collapsed before.
        if (!wasCollapsed)
            this.element.classList.remove(WI.NavigationBar.CollapsedStyleClassName);

        return totalItemWidth;
    }

    get _visibleNavigationItems()
    {
        return this._navigationItems.filter((item) => {
            if (item instanceof WI.FlexibleSpaceNavigationItem)
                return false;
            if (item.hidden || item[WI.NavigationBar.ForceHiddenSymbol])
                return false;
            return true;
        });
    }
};

WI.NavigationBar.ForceHiddenSymbol = Symbol("force-hidden");

WI.NavigationBar.CollapsedStyleClassName = "collapsed";

WI.NavigationBar.Event = {
    NavigationItemSelected: "navigation-bar-navigation-item-selected"
};
