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

        this._collapsedComponent = null;
        this._needsUpdate = false;

        this.components = components;
    }

    // Public

    get components()
    {
        return this._components;
    }

    set components(newComponents)
    {
        if (!newComponents)
            newComponents = [];

        let componentsEqual = function(a, b) {
            let getRepresentedObjects = (component) => component.representedObject;
            let representedObjectsA = a.map(getRepresentedObjects);
            let representedObjectsB = b.map(getRepresentedObjects);
            if (!Array.shallowEqual(representedObjectsA, representedObjectsB))
                return false;

            let getExtraComparisonData = (component) => component.comparisonData;
            let extraComparisonDataA = a.map(getExtraComparisonData);
            let extraComparisonDataB = b.map(getExtraComparisonData);
            return Array.shallowEqual(extraComparisonDataA, extraComparisonDataB);
        };

        if (this._components && componentsEqual(this._components, newComponents))
            return;

        if (this._components) {
            for (let component of this._components)
                component.removeEventListener(WI.HierarchicalPathComponent.Event.SiblingWasSelected, this._siblingPathComponentWasSelected, this);
        }

        this._components = newComponents.slice(0);

        for (let component of this._components)
            component.addEventListener(WI.HierarchicalPathComponent.Event.SiblingWasSelected, this._siblingPathComponentWasSelected, this);

        // Wait until layout to update the DOM.
        this._needsUpdate = true;

        // Update layout for the so other items can adjust to the extra space (or lack thereof) too.
        if (this.parentNavigationBar)
            this.parentNavigationBar.needsLayout();
    }

    get lastComponent()
    {
        return this._components.lastValue || null;
    }

    get alwaysShowLastPathComponentSeparator()
    {
        return this.element.classList.contains(WI.HierarchicalPathNavigationItem.AlwaysShowLastPathComponentSeparatorStyleClassName);
    }

    set alwaysShowLastPathComponentSeparator(flag)
    {
        if (flag)
            this.element.classList.add(WI.HierarchicalPathNavigationItem.AlwaysShowLastPathComponentSeparatorStyleClassName);
        else
            this.element.classList.remove(WI.HierarchicalPathNavigationItem.AlwaysShowLastPathComponentSeparatorStyleClassName);
    }

    updateLayout(expandOnly)
    {
        this._updateComponentsIfNeeded();

        super.updateLayout(expandOnly);

        var navigationBar = this.parentNavigationBar;
        if (!navigationBar)
            return;

        if (this._collapsedComponent) {
            this.element.removeChild(this._collapsedComponent.element);
            this._collapsedComponent = null;
        }

        // Expand our components to full width to test if the items can fit at full width.
        for (var i = 0; i < this._components.length; ++i) {
            this._components[i].hidden = false;
            this._components[i].forcedWidth = null;
            this._components[i].hideTooltip = true;
        }

        if (expandOnly)
            return;

        if (navigationBar.sizesToFit)
            return;

        // Iterate over all the other navigation items in the bar and calculate their width.
        var totalOtherItemsWidth = 0;
        for (var i = 0; i < navigationBar.navigationItems.length; ++i) {
            // Skip ourself.
            if (navigationBar.navigationItems[i] === this)
                continue;

            // Skip flexible space items since they can take up no space at the minimum width.
            if (navigationBar.navigationItems[i] instanceof WI.FlexibleSpaceNavigationItem)
                continue;

            totalOtherItemsWidth += navigationBar.navigationItems[i].element.realOffsetWidth;
        }

        // Calculate the width for all the components.
        var thisItemWidth = 0;
        var componentWidths = [];
        for (var i = 0; i < this._components.length; ++i) {
            var componentWidth = this._components[i].element.realOffsetWidth;
            componentWidths.push(componentWidth);
            thisItemWidth += componentWidth;
        }

        // If all our components fit with the other navigation items in the width of the bar,
        // then we don't need to collapse any components.
        var barWidth = navigationBar.element.realOffsetWidth;
        if (totalOtherItemsWidth + thisItemWidth <= barWidth)
            return;

        // Calculate the width we need to remove from our components, then iterate over them
        // and force their width to be smaller.
        var widthToRemove = totalOtherItemsWidth + thisItemWidth - barWidth;
        for (var i = 0; i < this._components.length; ++i) {
            var componentWidth = componentWidths[i];

            this._components[i].hideTooltip = false;

            // Try to take the whole width we need to remove from each component.
            var forcedWidth = componentWidth - widthToRemove;
            this._components[i].forcedWidth = forcedWidth;

            // Since components have a minimum width, we need to see how much was actually
            // removed and subtract that from what remans to be removed.
            componentWidths[i] = Math.max(this._components[i].minimumWidth, forcedWidth);
            widthToRemove -= componentWidth - componentWidths[i];

            // If there is nothing else to remove, then we can stop.
            if (widthToRemove <= 0)
                break;
        }

        // If there is nothing else to remove, then we can stop.
        if (widthToRemove <= 0)
            return;

        // If there are 3 or fewer components, then we can stop. Collapsing the middle of 3 components
        // does not save more than a few pixels over just the icon, so it isn't worth it unless there
        // are 4 or more components.
        if (this._components.length <= 3)
            return;

        // We want to collapse the middle components, so find the nearest middle index.
        var middle = this._components.length >> 1;
        var distance = -1;
        var i = middle;

        // Create a component that will represent the hidden components with a ellipse as the display name.
        this._collapsedComponent = new WI.HierarchicalPathComponent(ellipsis, []);
        this._collapsedComponent.collapsed = true;

        // Insert it in the middle, it doesn't matter exactly where since the elements around it will be hidden soon.
        this.element.insertBefore(this._collapsedComponent.element, this._components[middle].element);

        // Add the width of the collapsed component to the width we need to remove.
        widthToRemove += this._collapsedComponent.minimumWidth;

        var hiddenDisplayNames = [];

        // Loop through the components starting at the middle and fanning out in each direction.
        while (i >= 0 && i <= this._components.length - 1) {
            // Only hide components in the middle and never the ends.
            if (i > 0 && i < this._components.length - 1) {
                var component = this._components[i];
                component.hidden = true;

                // Remember the displayName so it can be put in the tool tip of the collapsed component.
                if (distance > 0)
                    hiddenDisplayNames.unshift(component.displayName);
                else
                    hiddenDisplayNames.push(component.displayName);

                // Fully subtract the hidden component's width.
                widthToRemove -= componentWidths[i];

                // If there is nothing else to remove, then we can stop.
                if (widthToRemove <= 0)
                    break;
            }

            // Calculate the next index.
            i = middle + distance;

            // Increment the distance when it is in the positive direction.
            if (distance > 0)
                ++distance;

            // Flip the direction of the distance.
            distance *= -1;
        }

        // Set the tool tip of the collapsed component.
        this._collapsedComponent.element.title = hiddenDisplayNames.join("\n");
    }

    // Protected

    get additionalClassNames()
    {
        return ["hierarchical-path"];
    }

    // Private

    _updateComponentsIfNeeded()
    {
        if (!this._needsUpdate)
            return;

        this._needsUpdate = false;

        this.element.removeChildren();
        this._collapsedComponent = null;

        for (let component of this._components)
            this.element.appendChild(component.element);
    }

    _siblingPathComponentWasSelected(event)
    {
        this.dispatchEventToListeners(WI.HierarchicalPathNavigationItem.Event.PathComponentWasSelected, event.data);
    }
};

WI.HierarchicalPathNavigationItem.AlwaysShowLastPathComponentSeparatorStyleClassName = "always-show-last-path-component-separator";

WI.HierarchicalPathNavigationItem.Event = {
    PathComponentWasSelected: "hierarchical-path-navigation-item-path-component-was-selected"
};
