/*
 * Copyright (C) 2013-2019 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.ResourceContentView = class ResourceContentView extends WI.ContentView
{
    constructor(resource, styleClassName)
    {
        console.assert(resource instanceof WI.Resource || resource instanceof WI.CSSStyleSheet, resource);
        console.assert(typeof styleClassName === "string");

        super(resource);

        this._resource = resource;

        this.element.classList.add(styleClassName, "resource");

        this._spinnerTimeout = setTimeout(() => {
            // Append a spinner while waiting for contentAvailable. Subclasses are responsible for
            // removing the spinner before showing the resource content by calling removeLoadingIndicator.
            let spinner = new WI.IndeterminateProgressSpinner;
            this.element.appendChild(spinner.element);

            this._spinnerTimeout = undefined;
        }, 100);

        this.element.addEventListener("click", this._mouseWasClicked.bind(this), false);

        // Request content last so the spinner will always be removed in case the content is immediately available.
        resource.requestContent().then(this._contentAvailable.bind(this)).catch(this.showGenericErrorMessage.bind(this));

        if (!this.managesOwnIssues) {
            WI.consoleManager.addEventListener(WI.ConsoleManager.Event.IssueAdded, this._issueWasAdded, this);

            var issues = WI.consoleManager.issuesForSourceCode(resource);
            for (var i = 0; i < issues.length; ++i)
                this.addIssue(issues[i]);
        }

        this._showingLocalResourceOverride = false;

        if (WI.NetworkManager.supportsLocalResourceOverrides()) {
            if (resource.isLocalResourceOverride) {
                this._showingLocalResourceOverride = true;

                this._localResourceOverrideBannerView = new WI.LocalResourceOverrideLabelView(resource);

                this._importLocalResourceOverrideButtonNavigationItem = new WI.ButtonNavigationItem("import-local-resource-override", WI.UIString("Import"), "Images/Import.svg", 15, 15);
                this._importLocalResourceOverrideButtonNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText;
                this._importLocalResourceOverrideButtonNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;
                this._importLocalResourceOverrideButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleImportLocalResourceOverride, this);

                this._removeLocalResourceOverrideButtonNavigationItem = new WI.ButtonNavigationItem("remove-local-resource-override", WI.UIString("Remove Local Override"), "Images/NavigationItemTrash.svg", 15, 15);
                this._removeLocalResourceOverrideButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleRemoveLocalResourceOverride, this);
                this._removeLocalResourceOverrideButtonNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;
            } else {
                this._localResourceOverrideBannerView = new WI.LocalResourceOverrideWarningView(resource);

                this._createLocalResourceOverrideButtonNavigationItem = new WI.ButtonNavigationItem("create-local-resource-override", this.createLocalResourceOverrideTooltip, "Images/NavigationItemNetworkOverride.svg", 13, 14);
                this._createLocalResourceOverrideButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleCreateLocalResourceOverride, this);
                this._createLocalResourceOverrideButtonNavigationItem.enabled = false; // Enabled when the content is available.
                this._createLocalResourceOverrideButtonNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;
            }

            WI.networkManager.addEventListener(WI.NetworkManager.Event.LocalResourceOverrideAdded, this._handleLocalResourceOverrideChanged, this);
            WI.networkManager.addEventListener(WI.NetworkManager.Event.LocalResourceOverrideRemoved, this._handleLocalResourceOverrideChanged, this);
        }
    }

    // Public

    get resource() { return this._resource; }
    get showingLocalResourceOverride() { return this._showingLocalResourceOverride; }

    get navigationItems()
    {
        let items = [];

        if (this._importLocalResourceOverrideButtonNavigationItem)
            items.push(this._importLocalResourceOverrideButtonNavigationItem, new WI.DividerNavigationItem);
        if (this._removeLocalResourceOverrideButtonNavigationItem)
            items.push(this._removeLocalResourceOverrideButtonNavigationItem);
        if (this._createLocalResourceOverrideButtonNavigationItem)
            items.push(this._createLocalResourceOverrideButtonNavigationItem);

        return items;
    }

    get supportsSave()
    {
        return this._resource.finished;
    }

    get saveData()
    {
        return {url: this._resource.url, content: this._resource.content};
    }

    contentAvailable(content, base64Encoded)
    {
        throw WI.NotImplementedError.subclassMustOverride();
    }

    get createLocalResourceOverrideTooltip()
    {
        return WI.UIString("Click to import a file and create a Local Override\nShift-click to create a Local Override from this content");
    }

    requestLocalResourceOverrideInitialContent(callback)
    {
        // Overridden by subclasses if needed.

        WI.FileUtilities.import(async (fileList) => {
            console.assert(fileList.length === 1);

            this._getContentForLocalResourceOverrideFromFile(fileList[0], ({mimeType, base64Encoded, content}) => {
                callback({
                    initialMIMEType: mimeType,
                    initialBase64Encoded: base64Encoded,
                    initialContent: content,
                });
            });
        });
    }

    showGenericNoContentMessage()
    {
        this.showMessage(WI.UIString("Resource has no content"));

        this.dispatchEventToListeners(WI.ResourceContentView.Event.ContentError);
    }

    showGenericErrorMessage()
    {
        this._contentError(WI.UIString("An error occurred trying to load the resource."));
    }

    showMessage(message)
    {
        this.element.removeChildren();
        this.element.appendChild(WI.createMessageTextView(message));
    }

    addIssue(issue)
    {
        // This generically shows only the last issue, subclasses can override for better handling.
        this.element.removeChildren();
        this.element.appendChild(WI.createMessageTextView(issue.text, issue.level === WI.IssueMessage.Level.Error));
    }

    closed()
    {
        super.closed();

        if (WI.NetworkManager.supportsLocalResourceOverrides())
            WI.networkManager.removeEventListener(null, null, this);

        if (!this.managesOwnIssues)
            WI.consoleManager.removeEventListener(null, null, this);
    }

    // Protected

    removeLoadingIndicator()
    {
        if (this._spinnerTimeout) {
            clearTimeout(this._spinnerTimeout);
            this._spinnerTimeout = undefined;
        }

        this.removeAllSubviews();

        if (this._localResourceOverrideBannerView)
            this.addSubview(this._localResourceOverrideBannerView);
    }

    // Private

    _contentAvailable(parameters)
    {
        if (parameters.error) {
            this._contentError(parameters.error);
            return;
        }

        if (parameters.message) {
            this.showMessage(parameters.message);
            return;
        }

        // Content is ready to show, call the public method now.
        console.assert(!this._hasContent());
        console.assert(parameters.sourceCode === this._resource);
        this.contentAvailable(parameters.sourceCode.content, parameters.base64Encoded);

        if (this._createLocalResourceOverrideButtonNavigationItem)
            this._createLocalResourceOverrideButtonNavigationItem.enabled = WI.networkManager.canBeOverridden(this._resource);
    }

    _contentError(error)
    {
        if (this._hasContent())
            return;

        this.removeLoadingIndicator();

        this.element.appendChild(WI.createMessageTextView(error, true));

        this.dispatchEventToListeners(WI.ResourceContentView.Event.ContentError);
    }

    _hasContent()
    {
        return this.element.hasChildNodes() && !this.element.querySelector(".indeterminate-progress-spinner");
    }

    _issueWasAdded(event)
    {
        console.assert(!this.managesOwnIssues);

        var issue = event.data.issue;
        if (!WI.ConsoleManager.issueMatchSourceCode(issue, this._resource))
            return;

        this.addIssue(issue);
    }

    async _getContentForLocalResourceOverrideFromFile(file, callback)
    {
        let initialMIMEType = file.type || WI.mimeTypeForFileExtension(WI.fileExtensionForFilename(file.name));
        if (WI.shouldTreatMIMETypeAsText(initialMIMEType)) {
            await WI.FileUtilities.readText(file, async ({text}) => {
                await callback({
                    mimeType: initialMIMEType,
                    base64Encoded: false,
                    content: text,
                });
            });
        } else {
            await WI.FileUtilities.readData(file, async ({mimeType, base64Encoded, content}) => {
                await callback({mimeType, base64Encoded, content});
            });
        }
    }

    _handleCreateLocalResourceOverride(event)
    {
        let {nativeEvent} = event.data;

        let createLocalResourceOverride = async (initialContent) => {
            let localResourceOverride = await this._resource.createLocalResourceOverride(initialContent);
            WI.networkManager.addLocalResourceOverride(localResourceOverride);
            WI.showLocalResourceOverride(localResourceOverride);
        };

        if (nativeEvent.shiftKey)
            createLocalResourceOverride({});
        else
            this.requestLocalResourceOverrideInitialContent(createLocalResourceOverride);
    }

    _handleImportLocalResourceOverride(event)
    {
        console.assert(this._showingLocalResourceOverride);

        WI.FileUtilities.import(async (fileList) => {
            console.assert(fileList.length === 1);

            let localResourceOverride = WI.networkManager.localResourceOverrideForURL(this.resource.url);
            console.assert(localResourceOverride);

            let revision = localResourceOverride.localResource.currentRevision;
            await this._getContentForLocalResourceOverrideFromFile(fileList[0], ({mimeType, base64Encoded, content}) => {
                revision.updateRevisionContent(content, {base64Encoded, mimeType});
            });

            if (!this.showingLocalResourceOverride)
                WI.showLocalResourceOverride(localResourceOverride);
        });
    }

    _handleRemoveLocalResourceOverride(event)
    {
        console.assert(this._showingLocalResourceOverride);

        let localResourceOverride = WI.networkManager.localResourceOverrideForURL(this._resource.url);
        WI.networkManager.removeLocalResourceOverride(localResourceOverride);
    }

    _handleLocalResourceOverrideChanged(event)
    {
        if (this._resource.url !== event.data.localResourceOverride.url)
            return;

        if (this._createLocalResourceOverrideButtonNavigationItem)
            this._createLocalResourceOverrideButtonNavigationItem.enabled = WI.networkManager.canBeOverridden(this._resource);
    }

    _mouseWasClicked(event)
    {
        WI.handlePossibleLinkClick(event, this._resource.parentFrame);
    }
};

WI.ResourceContentView.Event = {
    ContentError: "resource-content-view-content-error",
};
