/*
 * 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, navigationItems, role, label)
    {
        super(element);

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

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

        this.element.addEventListener("focus", this._focus.bind(this), false);
        this.element.addEventListener("blur", this._blur.bind(this), false);
        this.element.addEventListener("keydown", this._keyDown.bind(this), false);
        this.element.addEventListener("mousedown", this._mouseDown.bind(this), false);

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

        this._forceLayout = false;
        this._minimumWidth = NaN;
        this._navigationItems = [];
        this._selectedNavigationItem = null;

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

    // Public

    addNavigationItem(navigationItem, parentElement)
    {
        return this.insertNavigationItem(navigationItem, this._navigationItems.length, 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(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;
    }

    get sizesToFit()
    {
        // Can be overriden by subclasses.
        return false;
    }

    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;
    }

    needsLayout()
    {
        this._forceLayout = true;

        super.needsLayout();
    }

    layout()
    {
        if (this.layoutReason !== WI.View.LayoutReason.Resize && !this._forceLayout)
            return;

        this._forceLayout = false;

        // 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.updateLayout(true);
        }

        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.updateLayout(false);

        totalItemWidth = calculateVisibleItemWidth();

        if (totalItemWidth > barWidth) {
            // 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;

        // Remove the tabIndex so clicking the navigation bar does not give it focus.
        // Only keep the tabIndex if already focused from keyboard navigation. This matches Xcode.
        if (!this._focused)
            this.element.removeAttribute("tabindex");

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

        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);

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

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

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

        var itemElement = event.target.enclosingNodeOrSelfWithClass(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.enclosingNodeOrSelfWithClass(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);

        // Restore the tabIndex so the navigation bar can be in the keyboard tab loop.
        this.element.tabIndex = 0;

        // 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)
    {
        if (!this._focused)
            return;

        if (event.keyIdentifier !== "Left" && event.keyIdentifier !== "Right")
            return;

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

        var selectedNavigationItemIndex = this._navigationItems.indexOf(this._selectedNavigationItem);

        if (event.keyIdentifier === "Left") {
            if (selectedNavigationItemIndex === -1)
                selectedNavigationItemIndex = this._navigationItems.length;

            do {
                selectedNavigationItemIndex = Math.max(0, selectedNavigationItemIndex - 1);
            } while (selectedNavigationItemIndex && !(this._navigationItems[selectedNavigationItemIndex] instanceof WI.RadioButtonNavigationItem));
        } else if (event.keyIdentifier === "Right") {
            do {
                selectedNavigationItemIndex = Math.min(selectedNavigationItemIndex + 1, this._navigationItems.length - 1);
            } while (selectedNavigationItemIndex < this._navigationItems.length - 1 && !(this._navigationItems[selectedNavigationItemIndex] instanceof WI.RadioButtonNavigationItem));
        }

        if (!(this._navigationItems[selectedNavigationItemIndex] instanceof WI.RadioButtonNavigationItem))
            return;

        this.selectedNavigationItem = this._navigationItems[selectedNavigationItemIndex];
    }

    _focus(event)
    {
        this._focused = true;
    }

    _blur(event)
    {
        this._focused = false;
    }

    _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"
};
