/*
 * Copyright (C) 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.ObjectTreeView = class ObjectTreeView extends WI.Object
{
    constructor(object, mode, propertyPath, forceExpanding)
    {
        super();

        console.assert(object instanceof WI.RemoteObject);
        console.assert(!propertyPath || propertyPath instanceof WI.PropertyPath);

        var providedPropertyPath = propertyPath instanceof WI.PropertyPath;

        this._object = object;
        this._mode = mode || WI.ObjectTreeView.defaultModeForObject(object);
        this._propertyPath = propertyPath || new WI.PropertyPath(this._object, "this");
        this._expanded = false;
        this._hasLosslessPreview = false;
        this._includeProtoProperty = true;

        // If ObjectTree is used outside of the console, we do not know when to release
        // WeakMap entries. Currently collapse would work. For the console, we can just
        // listen for console clear events. Currently all ObjectTrees are in the console.
        this._inConsole = true;

        this._fetchStart = 0;
        this._fetchEnd = ObjectTreeView.showMoreFetchCount;
        this._fetchEndIndex = 0;

        // Always force expanding for classes.
        if (this._object.isClass())
            forceExpanding = true;

        this._element = document.createElement("div");
        this._element.__objectTree = this;
        this._element.className = "object-tree";

        if (this._object.preview) {
            this._previewView = new WI.ObjectPreviewView(this._object, this._object.preview);
            this._previewView.setOriginatingObjectInfo(this._object, providedPropertyPath ? propertyPath : null);
            this._previewView.element.addEventListener("click", this._handlePreviewOrTitleElementClick.bind(this));
            this._element.appendChild(this._previewView.element);

            if (this._previewView.lossless && !this._propertyPath.parent && !forceExpanding) {
                this._hasLosslessPreview = true;
                this.element.classList.add("lossless-preview");
            }
        } else {
            this._titleElement = document.createElement("span");
            this._titleElement.className = "title";
            this._titleElement.appendChild(WI.FormattedValue.createElementForRemoteObject(this._object));
            this._titleElement.addEventListener("click", this._handlePreviewOrTitleElementClick.bind(this));
            this._element.appendChild(this._titleElement);
        }

        this._outline = new WI.TreeOutline;
        this._outline.compact = true;
        this._outline.customIndent = true;
        this._outline.element.classList.add("object");
        this._element.appendChild(this._outline.element);

        // FIXME: Support editable ObjectTrees.
    }

    // Static

    static defaultModeForObject(object)
    {
        if (object.subtype === "class")
            return WI.ObjectTreeView.Mode.ClassAPI;

        return WI.ObjectTreeView.Mode.Properties;
    }

    static createEmptyMessageElement(message)
    {
        var emptyMessageElement = document.createElement("div");
        emptyMessageElement.className = "empty-message";
        emptyMessageElement.textContent = message;
        return emptyMessageElement;
    }

    static get showMoreFetchCount() { return 100; }

    static addShowMoreIfNeeded({resolvedValue, representation, parentTreeElement, handleShowMoreClicked, handleShowAllClicked})
    {
        console.assert(resolvedValue instanceof WI.RemoteObject, resolvedValue);
        console.assert(resolvedValue.isArray() || resolvedValue.isCollectionType());
        console.assert(typeof resolvedValue.size === "number" && resolvedValue.size > 0, resolvedValue);
        console.assert("_fetchStart" in representation, representation);
        console.assert("_fetchEnd" in representation, representation);
        console.assert("_fetchEndIndex" in representation, representation);
        console.assert(typeof handleShowMoreClicked === "function", handleShowMoreClicked);
        console.assert(typeof handleShowAllClicked === "function", handleShowAllClicked);

        // COMPATIBILITY (iOS 13): Runtime.getProperties/Runtime.getDisplayableProperties didn't support `fetchStart`/`fetchCount` yet.
        if (!InspectorBackend.hasCommand("Runtime.getProperties", "fetchStart"))
            return;

        let remaining = resolvedValue.size - representation._fetchEnd;
        if (remaining <= 0)
            return;

        let treeElement = new WI.TreeElement(document.createElement("span"));
        treeElement.selectable = false;
        parentTreeElement.insertChild(treeElement, representation._fetchEndIndex);

        // FIXME: <https://webkit.org/b/201965> Web Inspector: allow examining items in the middle of an array/collection without having to show all items before

        let buttons = [];
        let createButton = (textContent, handleClick) => {
            let button = treeElement.title.appendChild(document.createElement("button"));
            button.textContent = textContent;
            button.addEventListener("click", (event) => {
                event.stop();

                representation.singleFireEventListener(ObjectTreeView.Event.Updated, () => {
                    // The `treeElement` may have already been removed by some other means (e.g. `removeChildren`).
                    if (treeElement.parent === parentTreeElement)
                        parentTreeElement.removeChild(treeElement);
                });

                for (let other of buttons)
                    other.disabled = true;

                let spinner = new WI.IndeterminateProgressSpinner;
                button.insertAdjacentElement("afterend", spinner.element);

                handleClick();
            });
            buttons.push(button);
        };

        if (!resolvedValue.isWeakCollection() && remaining > ObjectTreeView.showMoreFetchCount) {
            createButton(WI.UIString("Show %d More").format(ObjectTreeView.showMoreFetchCount), () => {
                representation._fetchStart = representation._fetchEnd;
                representation._fetchEnd = representation._fetchStart + ObjectTreeView.showMoreFetchCount;
                handleShowMoreClicked();
            });
        }

        createButton(WI.UIString("Show All (%d More)").format(remaining), () => {
            representation._fetchStart = 0;
            representation._fetchEnd = Infinity;
            representation._fetchEndIndex = 0;
            handleShowAllClicked();
        });
    }

    static comparePropertyDescriptors(propertyA, propertyB)
    {
        var a = propertyA.name;
        var b = propertyB.name;

        // Put __proto__ at the bottom.
        if (a === "__proto__")
            return 1;
        if (b === "__proto__")
            return -1;

        // Put Internal properties at the top.
        if (propertyA.isInternalProperty && !propertyB.isInternalProperty)
            return -1;
        if (propertyB.isInternalProperty && !propertyA.isInternalProperty)
            return 1;

        // Put Symbol properties at the bottom.
        if (propertyA.symbol && !propertyB.symbol)
            return 1;
        if (propertyB.symbol && !propertyA.symbol)
            return -1;

        // Symbol properties may have the same description string but be different objects.
        if (a === b)
            return 0;

        var diff = 0;
        var chunk = /^\d+|^\D+/;
        var chunka, chunkb, anum, bnum;
        while (diff === 0) {
            if (!a && b)
                return -1;
            if (!b && a)
                return 1;
            chunka = a.match(chunk)[0];
            chunkb = b.match(chunk)[0];
            anum = !isNaN(chunka);
            bnum = !isNaN(chunkb);
            if (anum && !bnum)
                return -1;
            if (bnum && !anum)
                return 1;
            if (anum && bnum) {
                diff = chunka - chunkb;
                if (diff === 0 && chunka.length !== chunkb.length) {
                    if (!+chunka && !+chunkb) // chunks are strings of all 0s (special case)
                        return chunka.length - chunkb.length;
                    else
                        return chunkb.length - chunka.length;
                }
            } else if (chunka !== chunkb)
                return chunka < chunkb ? -1 : 1;
            a = a.substring(chunka.length);
            b = b.substring(chunkb.length);
        }
        return diff;
    }

    // Public

    get object()
    {
        return this._object;
    }

    get element()
    {
        return this._element;
    }

    get treeOutline()
    {
        return this._outline;
    }

    get expanded()
    {
        return this._expanded;
    }

    expand()
    {
        if (this._expanded)
            return;

        if (this._hasLosslessPreview)
            return;

        this._expanded = true;
        this._element.classList.add("expanded");

        if (this._previewView)
            this._previewView.showTitle();

        this._trackWeakEntries();

        this.update();
    }

    collapse()
    {
        if (!this._expanded)
            return;

        this._expanded = false;
        this._element.classList.remove("expanded");

        if (this._previewView)
            this._previewView.showPreview();

        this._untrackWeakEntries();
    }

    showOnlyProperties()
    {
        this._inConsole = false;

        this._element.classList.add("properties-only");

        this._includeProtoProperty = false;
    }

    showOnlyJSON()
    {
        this.showOnlyProperties();

        this._element.classList.add("json-only");
    }

    appendTitleSuffix(suffixElement)
    {
        if (this._previewView)
            this._previewView.element.appendChild(suffixElement);
        else
            this._titleElement.appendChild(suffixElement);
    }

    appendExtraPropertyDescriptor(propertyDescriptor)
    {
        if (!this._extraProperties)
            this._extraProperties = [];

        this._extraProperties.push(propertyDescriptor);
    }

    setPrototypeNameOverride(override)
    {
        this._prototypeNameOverride = override;
    }

    // Protected

    update()
    {
        this._fetchStart = 0;
        this._fetchEndIndex = 0;
        this._updateChildren();
    }

    // Private

    _updateChildren()
    {
        let options = {
            ownProperties: true,
            generatePreview: true,
        };

        if (isFinite(this._fetchEnd) && this._fetchEnd < this._object.size) {
            options.fetchStart = this._fetchStart;
            options.fetchCount = this._fetchEnd - this._fetchStart;
        }

        let wrap = (handler) => (list) => {
            if (this._fetchEndIndex === 0)
                this._outline.removeChildren();

            if (!list) {
                let errorMessageElement = WI.ObjectTreeView.createEmptyMessageElement(WI.UIString("Could not fetch properties. Object may no longer exist."));
                this._outline.appendChild(new WI.TreeElement(errorMessageElement));
                return;
            }

            handler.call(this, list, this._propertyPath);

            this.dispatchEventToListeners(ObjectTreeView.Event.Updated);
        };

        if (this._object.isCollectionType() && this._mode === ObjectTreeView.Mode.Properties)
            this._object.getCollectionEntries(wrap(this._updateEntries), options);
        else if (this._object.isClass())
            this._object.classPrototype.getDisplayablePropertyDescriptors(wrap(this._updateProperties), options);
        else if (this._mode === ObjectTreeView.Mode.PureAPI)
            this._object.getPropertyDescriptors(wrap(this._updateProperties), options);
        else
            this._object.getDisplayablePropertyDescriptors(wrap(this._updateProperties), options);
    }

    _updateEntries(entries, propertyPath)
    {
        entries.forEach((entry, i) => {
            if (entry.key) {
                this._outline.insertChild(new WI.ObjectTreeMapKeyTreeElement(entry.key, propertyPath), this._fetchEndIndex++);
                this._outline.insertChild(new WI.ObjectTreeMapValueTreeElement(entry.value, propertyPath, entry.key), this._fetchEndIndex++);
            } else
                this._outline.insertChild(new WI.ObjectTreeSetIndexTreeElement(entry.value, propertyPath), this._fetchEndIndex++);
        });

        if (!this._outline.children.length) {
            let emptyMessageElement = ObjectTreeView.createEmptyMessageElement(WI.UIString("No Entries"));
            this._outline.appendChild(new WI.TreeElement(emptyMessageElement));
        } else {
            console.assert(this._mode === WI.ObjectTreeView.Mode.Properties);
            ObjectTreeView.addShowMoreIfNeeded({
                resolvedValue: this._object,
                representation: this,
                parentTreeElement: this._outline,
                handleShowMoreClicked: () => {
                    this._updateChildren();
                },
                handleShowAllClicked: () => {
                    this.update();
                },
            });
        }

        // Show the prototype so users can see the API, but only fetch it the first time.
        if (this._fetchStart === 0) {
            this._object.getOwnPropertyDescriptor("__proto__", (propertyDescriptor) => {
                if (propertyDescriptor)
                    this._outline.appendChild(new WI.ObjectTreePropertyTreeElement(propertyDescriptor, propertyPath, this._mode));
            });
        }
    }

    _updateProperties(properties, propertyPath)
    {
        if (this._extraProperties)
            properties.pushAll(this._extraProperties);

        properties.sort(WI.ObjectTreeView.comparePropertyDescriptors);

        var isArray = this._object.isArray();
        var isPropertyMode = this._mode === WI.ObjectTreeView.Mode.Properties;

        var hadProto = false;
        for (var propertyDescriptor of properties) {
            if (propertyDescriptor.name === "__proto__") {
                // COMPATIBILITY (iOS 8): Sometimes __proto__ is not a value, but a get/set property.
                // In those cases it is actually not useful to show.
                if (!propertyDescriptor.hasValue())
                    continue;
                if (!this._includeProtoProperty)
                    continue;
                hadProto = true;
                this._outline.appendChild(new WI.ObjectTreePropertyTreeElement(propertyDescriptor, propertyPath, this._mode, this._prototypeNameOverride));
                continue;
            }

            if (isArray && isPropertyMode) {
                if (propertyDescriptor.isIndexProperty())
                    this._outline.insertChild(new WI.ObjectTreeArrayIndexTreeElement(propertyDescriptor, propertyPath), this._fetchEndIndex++);
            } else
                this._outline.insertChild(new WI.ObjectTreePropertyTreeElement(propertyDescriptor, propertyPath, this._mode, this._prototypeNameOverride), this._fetchEndIndex++);
        }

        if (!this._outline.children.length || (hadProto && this._outline.children.length === 1)) {
            let emptyMessageElement = ObjectTreeView.createEmptyMessageElement(WI.UIString("No Properties"));
            this._outline.insertChild(new WI.TreeElement(emptyMessageElement), 0);
        } else if (isArray && isPropertyMode) {
            ObjectTreeView.addShowMoreIfNeeded({
                resolvedValue: this._object,
                representation: this,
                parentTreeElement: this._outline,
                handleShowMoreClicked: () => {
                    this._updateChildren();
                },
                handleShowAllClicked: () => {
                    this.update();
                },
            });
        }
    }

    _handlePreviewOrTitleElementClick(event)
    {
        if (this._hasLosslessPreview)
            return;

        if (!this._expanded)
            this.expand();
        else
            this.collapse();

        event.stopPropagation();
    }

    _trackWeakEntries()
    {
        if (this._trackingEntries)
            return;

        if (!this._object.isWeakCollection())
            return;

        this._trackingEntries = true;

        if (this._inConsole) {
            WI.consoleManager.addEventListener(WI.ConsoleManager.Event.Cleared, this._untrackWeakEntries, this);
            WI.consoleManager.addEventListener(WI.ConsoleManager.Event.SessionStarted, this._untrackWeakEntries, this);
        }
    }

    _untrackWeakEntries()
    {
        if (!this._trackingEntries)
            return;

        if (!this._object.isWeakCollection())
            return;

        this._trackingEntries = false;

        this._object.releaseWeakCollectionEntries();

        if (this._inConsole) {
            WI.consoleManager.removeEventListener(WI.ConsoleManager.Event.Cleared, this._untrackWeakEntries, this);
            WI.consoleManager.removeEventListener(WI.ConsoleManager.Event.SessionStarted, this._untrackWeakEntries, this);
        }

        // FIXME: This only tries to release weak entries if this object was a WeakMap.
        // If there was a WeakMap expanded in a sub-object, we will never release those values.
        // Should we attempt walking the entire tree and release weak collections?
    }
};

WI.ObjectTreeView.Mode = {
    Properties: Symbol("object-tree-properties"),      // Properties
    PrototypeAPI: Symbol("object-tree-prototype-api"), // API view on a live object instance, so getters can be invoked.
    ClassAPI: Symbol("object-tree-class-api"),         // API view without an object instance, can not invoke getters.
    PureAPI: Symbol("object-tree-pure-api"),           // API view without special displayable property handling, just own properties. Getters can be invoked if the property path has a non-prototype object.
};

WI.ObjectTreeView.Event = {
    Updated: "object-tree-updated",
};
