/*
 * Copyright (C) 2018 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.NetworkDetailView = class NetworkDetailView extends WI.View
{
    constructor(representedObject, delegate)
    {
        super();

        this._representedObject = representedObject;
        this._delegate = delegate || null;

        this.element.classList.add("network-detail");

        this._contentBrowser = null;

        this._detailNavigationItemMap = new Map;

        this._contentViewCookie = null;
    }

    // Public

    get representedObject() { return this._representedObject; }

    shown()
    {
        if (!this._contentBrowser)
            return;

        this._showPreferredContentView();

        if (this._contentViewCookie) {
            this._contentBrowser.showContentView(this._contentBrowser.currentContentView, this._contentViewCookie);
            this._contentViewCookie = null;
        }

        this._contentBrowser.shown();
    }

    hidden()
    {
        this._contentBrowser.hidden();
    }

    dispose()
    {
        this._delegate = null;

        this._contentBrowser.contentViewContainer.closeAllContentViews();
    }

    willShowWithCookie(cookie)
    {
        this._contentViewCookie = cookie;
    }

    // Protected

    initialLayout()
    {
        let closeNavigationItem = new WI.ButtonNavigationItem("close", WI.UIString("Close detail view"), "Images/CloseLarge.svg", 16, 16);
        closeNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleCloseButton.bind(this));
        closeNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.High;

        let contentViewNavigationItemsGroup = new WI.GroupNavigationItem;
        let contentViewNavigationItemsFlexItem = new WI.FlexibleSpaceNavigationItem(contentViewNavigationItemsGroup, WI.FlexibleSpaceNavigationItem.Align.End);
        contentViewNavigationItemsFlexItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;

        const element = null;
        const disableBackForward = true;
        const disableFindBanner = false;
        this._contentBrowser = new WI.ContentBrowser(element, this, disableBackForward, disableFindBanner, contentViewNavigationItemsFlexItem, contentViewNavigationItemsGroup);

        // Insert all of our custom navigation items at the start of the ContentBrowser's NavigationBar.
        let index = 0;
        this._contentBrowser.navigationBar.insertNavigationItem(closeNavigationItem, index++);
        this._contentBrowser.navigationBar.insertNavigationItem(new WI.FlexibleSpaceNavigationItem, index++);
        for (let detailNavigationItem of this._detailNavigationItemMap.values())
            this._contentBrowser.navigationBar.insertNavigationItem(detailNavigationItem, index++);

        this._contentBrowser.navigationBar.addEventListener(WI.NavigationBar.Event.NavigationItemSelected, this._navigationItemSelected, this);

        this.addSubview(this._contentBrowser);

        this._showPreferredContentView();
    }

    createDetailNavigationItem(identifier, toolTip)
    {
        this._detailNavigationItemMap.set(identifier, new WI.RadioButtonNavigationItem(identifier, toolTip));
    }

    detailNavigationItemForIdentifier(identifier)
    {
        return this._detailNavigationItemMap.get(identifier);
    }

    showContentViewForIdentifier(identifier)
    {
        // Implemented by subclasses.
    }

    // Private

    _showPreferredContentView()
    {
        let detailNavigationItems = Array.from(this._detailNavigationItemMap.values());

        // Restore the preferred navigation item.
        let firstNavigationItem = null;
        let defaultIdentifier = WI.settings.selectedNetworkDetailContentViewIdentifier.value;
        for (let navigationItem of this._contentBrowser.navigationBar.navigationItems) {
            if (!(navigationItem instanceof WI.RadioButtonNavigationItem))
                continue;

            if (!detailNavigationItems.includes(navigationItem))
                continue;

            if (!firstNavigationItem)
                firstNavigationItem = navigationItem;

            if (navigationItem.identifier === defaultIdentifier) {
                this._contentBrowser.navigationBar.selectedNavigationItem = navigationItem;
                return;
            }
        }

        console.assert(firstNavigationItem, "Should have found at least one navigation item above");
        this._contentBrowser.navigationBar.selectedNavigationItem = firstNavigationItem;
    }

    _navigationItemSelected(event)
    {
        let navigationItem = event.target.selectedNavigationItem;
        if (!(navigationItem instanceof WI.RadioButtonNavigationItem))
            return;

        this.showContentViewForIdentifier(navigationItem.identifier);

        console.assert(navigationItem.identifier);
        WI.settings.selectedNetworkDetailContentViewIdentifier.value = navigationItem.identifier;
    }

    _handleCloseButton(event)
    {
        if (this._delegate && this._delegate.networkDetailViewClose)
            this._delegate.networkDetailViewClose(this);
    }
};
