/*
 * 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.ScopeBar = class ScopeBar extends WI.NavigationItem
{
    constructor(identifier, items, defaultItem, shouldGroupNonExclusiveItems)
    {
        super(identifier);

        this._element.classList.add("scope-bar");

        this._items = items;
        this._defaultItem = defaultItem;
        this._shouldGroupNonExclusiveItems = shouldGroupNonExclusiveItems || false;

        for (let item of this._items)
            item.scopeBar = this;

        this._minimumWidth = 0;

        this._populate();

        this._element.addEventListener("keydown", this._handleKeyDown.bind(this));
    }

    // Public

    get minimumWidth()
    {
        if (!this._minimumWidth) {
            // If a "display: flex;" element is too small for its contents and
            // has "flex-wrap: wrap;" set as well, this will cause the contents
            // to wrap (potentially overflowing), thus preventing a proper
            // measurement of the width of the element. Removing the "flex-wrap"
            // property will ensure that the contents are rendered on one line.
            this.element.style.flexWrap = "initial !important";

            if (this._multipleItem)
                this._multipleItem.displayWidestItem();

            this._minimumWidth = this.element.realOffsetWidth;
            this.element.style.flexWrap = null;

            if (this._multipleItem)
                this._multipleItem.displaySelectedItem();
        }
        return this._minimumWidth;
    }

    get defaultItem()
    {
        return this._defaultItem;
    }

    get items()
    {
        return this._items;
    }

    item(id)
    {
        return this._itemsById.get(id);
    }

    get selectedItems()
    {
        return this._items.filter((item) => item.selected);
    }

    hasNonDefaultItemSelected()
    {
        return this._items.some((item) => item.selected && item !== this._defaultItem);
    }

    resetToDefault()
    {
        let selectedItems = this.selectedItems;
        if (selectedItems.length === 1 && selectedItems[0] === this._defaultItem)
            return;

        for (let item of this._items)
            item.selected = false;
        this._defaultItem.selected = true;

        this.dispatchEventToListeners(WI.ScopeBar.Event.SelectionChanged);
    }

    // Private

    _populate()
    {
        this._itemsById = new Map;

        if (this._shouldGroupNonExclusiveItems) {
            var nonExclusiveItems = [];

            for (var item of this._items) {
                this._itemsById.set(item.id, item);

                if (item.exclusive)
                    this._element.appendChild(item.element);
                else
                    nonExclusiveItems.push(item);

                item.addEventListener(WI.ScopeBarItem.Event.SelectionChanged, this._itemSelectionDidChange, this);
            }

            this._multipleItem = new WI.MultipleScopeBarItem(nonExclusiveItems);
            this._element.appendChild(this._multipleItem.element);
        } else {
            for (var item of this._items) {
                this._itemsById.set(item.id, item);
                this._element.appendChild(item.element);

                item.addEventListener(WI.ScopeBarItem.Event.SelectionChanged, this._itemSelectionDidChange, this);
            }
        }

        if (this._defaultItem) {
            if (!this.selectedItems.length)
                this._defaultItem.selected = true;

            this._element.classList.toggle("default-item-selected", this._defaultItem.selected);
        }
    }

    _itemSelectionDidChange(event)
    {
        var sender = event.target;
        var item;

        // An exclusive item was selected, unselect everything else.
        if (sender.exclusive && sender.selected) {
            for (var i = 0; i < this._items.length; ++i) {
                item = this._items[i];
                if (item !== sender)
                    item.selected = false;
            }
        } else {
            let replacesCurrentSelection = this._shouldGroupNonExclusiveItems || !event.data.extendSelection;
            for (var i = 0; i < this._items.length; ++i) {
                item = this._items[i];
                if (item.exclusive && item !== sender && sender.selected)
                    item.selected = false;
                else if (sender.selected && replacesCurrentSelection && sender !== item)
                    item.selected = false;
            }
        }

        if (this._defaultItem) {
            if (!this.selectedItems.length)
                this._defaultItem.selected = true;

            this._element.classList.toggle("default-item-selected", this._defaultItem.selected);
        }

        this.dispatchEventToListeners(WI.ScopeBar.Event.SelectionChanged);
    }

    _handleKeyDown(event)
    {
        if (event.code === "ArrowLeft" || event.code === "ArrowRight") {
            event.stop();
            let focusedIndex = -1;

            for (let i = 0; i < this._items.length; ++i) {
                let element = this._items[i].element;
                if (element === document.activeElement) {
                    focusedIndex = i;
                    break;
                }
            }

            if (focusedIndex === -1)
                return;

            let delta = (event.code === "ArrowLeft") ? -1 : 1;
            if (WI.resolveLayoutDirectionForElement(this._element) === WI.LayoutDirection.RTL)
                delta *= -1;

            focusedIndex += delta;
            focusedIndex = (focusedIndex + this._items.length) % this._items.length;
            this._items[focusedIndex].element.focus();
        }
    }
};

WI.ScopeBar.Event = {
    SelectionChanged: "scopebar-selection-did-change"
};
