/*
 * Copyright (C) 2014-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.FolderizedTreeElement = class FolderizedTreeElement extends WI.GeneralTreeElement
{
    constructor(classNames, title, subtitle, representedObject)
    {
        super(classNames, title, subtitle, representedObject);

        this.shouldRefreshChildren = true;

        this._folderExpandedSettingMap = new Map;
        this._folderSettingsKey = "";
        this._folderTypeMap = new Map;
        this._folderizeSettingsMap = new Map;
        this._groupedIntoFolders = false;
        this._clearNewChildQueue();
    }

    // Public

    get groupedIntoFolders()
    {
        return this._groupedIntoFolders;
    }

    set folderSettingsKey(x)
    {
        this._folderSettingsKey = x;
    }

    registerFolderizeSettings(type, displayName, representedObject, treeElementConstructor)
    {
        console.assert(type);
        console.assert(displayName || displayName === null);
        console.assert(representedObject);
        console.assert(typeof treeElementConstructor === "function");

        let settings = {
            type,
            displayName,
            topLevel: displayName === null,
            representedObject,
            treeElementConstructor,
        };

        this._folderizeSettingsMap.set(type, settings);
    }

    removeChildren()
    {
        super.removeChildren();

        this._clearNewChildQueue();

        this._folderExpandedSettingMap.clear();
        this._folderTypeMap.clear();

        this._groupedIntoFolders = false;
    }

    // Protected

    addChildForRepresentedObject(representedObject)
    {
        var settings = this._settingsForRepresentedObject(representedObject);
        console.assert(settings);
        if (!settings) {
            console.error("No settings for represented object", representedObject);
            return;
        }

        if (!this.treeOutline) {
            // Just mark as needing to update to avoid doing work that might not be needed.
            this.shouldRefreshChildren = true;
            return;
        }

        var childTreeElement = this.treeOutline.getCachedTreeElement(representedObject);
        if (!childTreeElement)
            childTreeElement = new settings.treeElementConstructor(representedObject);

        this._addTreeElement(childTreeElement);
    }

    addRepresentedObjectToNewChildQueue(representedObject)
    {
        // This queue reduces flashing as resources load and change folders when their type becomes known.

        this._newChildQueue.push(representedObject);
        if (!this._newChildQueueTimeoutIdentifier)
            this._newChildQueueTimeoutIdentifier = setTimeout(this._populateFromNewChildQueue.bind(this), WI.FolderizedTreeElement.NewChildQueueUpdateInterval);
    }

    removeChildForRepresentedObject(representedObject)
    {
        this._removeRepresentedObjectFromNewChildQueue(representedObject);
        this.updateParentStatus();

        if (!this.treeOutline) {
            // Just mark as needing to update to avoid doing work that might not be needed.
            this.shouldRefreshChildren = true;
            return;
        }

        // Find the tree element for the frame by using getCachedTreeElement
        // to only get the item if it has been created already.
        var childTreeElement = this.treeOutline.getCachedTreeElement(representedObject);
        if (!childTreeElement || !childTreeElement.parent)
            return;

        this._removeTreeElement(childTreeElement);
    }

    compareChildTreeElements(a, b)
    {
        return this._compareTreeElementsByMainTitle(a, b);
    }

    updateParentStatus()
    {
        let hasChildren = false;
        for (let settings of this._folderizeSettingsMap.values()) {
            if (settings.representedObject.size) {
                hasChildren = true;
                break;
            }
        }

        this.hasChildren = hasChildren;
        if (!this.hasChildren)
            this.removeChildren();
    }

    prepareToPopulate()
    {
        if (!this._groupedIntoFolders && this._shouldGroupIntoFolders()) {
            this._groupedIntoFolders = true;
            return true;
        }

        return false;
    }

    // Private

    _clearNewChildQueue()
    {
        this._newChildQueue = [];
        if (this._newChildQueueTimeoutIdentifier) {
            clearTimeout(this._newChildQueueTimeoutIdentifier);
            this._newChildQueueTimeoutIdentifier = null;
        }
    }

    _populateFromNewChildQueue()
    {
        if (!this.children.length) {
            this.updateParentStatus();
            this.shouldRefreshChildren = true;
            return;
        }

        if (this.prepareToPopulate()) {
            // Will now folderize, repopulate children.
            this._clearNewChildQueue();
            this.shouldRefreshChildren = true;
            return;
        }

        for (var i = 0; i < this._newChildQueue.length; ++i)
            this.addChildForRepresentedObject(this._newChildQueue[i]);

        this._clearNewChildQueue();
    }

    _removeRepresentedObjectFromNewChildQueue(representedObject)
    {
        this._newChildQueue.remove(representedObject);
    }

    _addTreeElement(childTreeElement)
    {
        console.assert(childTreeElement);
        if (!childTreeElement)
            return;

        var wasSelected = childTreeElement.selected;

        this._removeTreeElement(childTreeElement, true, true);

        var parentTreeElement = this._parentTreeElementForRepresentedObject(childTreeElement.representedObject);
        if (parentTreeElement !== this && !parentTreeElement.parent)
            this._insertFolderTreeElement(parentTreeElement);

        this._insertChildTreeElement(parentTreeElement, childTreeElement);

        if (wasSelected)
            childTreeElement.revealAndSelect(true, false, true);
    }

    _compareTreeElementsByMainTitle(a, b)
    {
        // Folders before anything.
        let aIsFolder = a instanceof WI.FolderTreeElement;
        let bIsFolder = b instanceof WI.FolderTreeElement;
        if (aIsFolder && !bIsFolder)
            return -1;
        if (bIsFolder && !aIsFolder)
            return 1;

        // Then sort by title.
        return a.mainTitle.extendedLocaleCompare(b.mainTitle);
    }

    _insertFolderTreeElement(folderTreeElement)
    {
        console.assert(this._groupedIntoFolders);
        console.assert(!folderTreeElement.parent);
        this.insertChild(folderTreeElement, insertionIndexForObjectInListSortedByFunction(folderTreeElement, this.children, this._compareTreeElementsByMainTitle));
    }

    _insertChildTreeElement(parentTreeElement, childTreeElement)
    {
        console.assert(!childTreeElement.parent);
        parentTreeElement.insertChild(childTreeElement, insertionIndexForObjectInListSortedByFunction(childTreeElement, parentTreeElement.children, this.compareChildTreeElements.bind(this)));
    }

    _removeTreeElement(childTreeElement, suppressOnDeselect, suppressSelectSibling)
    {
        var oldParent = childTreeElement.parent;
        if (!oldParent)
            return;

        oldParent.removeChild(childTreeElement, suppressOnDeselect, suppressSelectSibling);

        if (oldParent === this)
            return;

        console.assert(oldParent instanceof WI.FolderTreeElement);
        if (!(oldParent instanceof WI.FolderTreeElement))
            return;

        // Remove the old parent folder if it is now empty.
        if (!oldParent.children.length)
            oldParent.parent.removeChild(oldParent);
    }

    _parentTreeElementForRepresentedObject(representedObject)
    {
        if (!this._groupedIntoFolders)
            return this;

        console.assert(this._folderSettingsKey !== "");

        function createFolderTreeElement(settings)
        {
            let folderTreeElement = new WI.FolderTreeElement(settings.displayName, settings.representedObject);
            let folderExpandedSetting = new WI.Setting(settings.type + "-folder-expanded-" + this._folderSettingsKey, false);
            this._folderExpandedSettingMap.set(folderTreeElement, folderExpandedSetting);

            if (folderExpandedSetting.value)
                folderTreeElement.expand();

            folderTreeElement.onexpand = this._folderTreeElementExpandedStateChange.bind(this);
            folderTreeElement.oncollapse = this._folderTreeElementExpandedStateChange.bind(this);
            return folderTreeElement;
        }

        var settings = this._settingsForRepresentedObject(representedObject);
        if (!settings) {
            console.error("Unknown representedObject", representedObject);
            return this;
        }

        if (settings.topLevel)
            return this;

        var folder = this._folderTypeMap.get(settings.type);
        if (folder)
            return folder;

        folder = createFolderTreeElement.call(this, settings);
        this._folderTypeMap.set(settings.type, folder);
        return folder;
    }

    _folderTreeElementExpandedStateChange(folderTreeElement)
    {
        let expandedSetting = this._folderExpandedSettingMap.get(folderTreeElement);
        console.assert(expandedSetting, "No expanded setting for folderTreeElement", folderTreeElement);
        if (!expandedSetting)
            return;

        expandedSetting.value = folderTreeElement.expanded;
    }

    _settingsForRepresentedObject(representedObject)
    {
        for (let settings of this._folderizeSettingsMap.values()) {
            if (settings.representedObject.objectIsRequiredType(representedObject))
                return settings;
        }
        return null;
    }

    _shouldGroupIntoFolders()
    {
        // Already grouped into folders, keep it that way.
        if (this._groupedIntoFolders)
            return true;

        // Child objects are grouped into folders if one of two thresholds are met:
        // 1) Once the number of medium categories passes NumberOfMediumCategoriesThreshold.
        // 2) When there is a category that passes LargeChildCountThreshold and there are
        //    any child objects in another category.

        // Folders are avoided when there is only one category or most categories are small.

        var numberOfSmallCategories = 0;
        var numberOfMediumCategories = 0;
        var foundLargeCategory = false;

        function pushCategory(childCount)
        {
            if (!childCount)
                return false;

            // If this type has any resources and there is a known large category, make folders.
            if (foundLargeCategory)
                return true;

            // If there are lots of this resource type, then count it as a large category.
            if (childCount >= WI.FolderizedTreeElement.LargeChildCountThreshold) {
                // If we already have other resources in other small or medium categories, make folders.
                if (numberOfSmallCategories || numberOfMediumCategories)
                    return true;

                foundLargeCategory = true;
                return false;
            }

            // Check if this is a medium category.
            if (childCount >= WI.FolderizedTreeElement.MediumChildCountThreshold) {
                // If this is the medium category that puts us over the maximum allowed, make folders.
                return ++numberOfMediumCategories >= WI.FolderizedTreeElement.NumberOfMediumCategoriesThreshold;
            }

            // This is a small category.
            ++numberOfSmallCategories;
            return false;
        }

        // Iterate over all the available child object types.
        for (var settings of this._folderizeSettingsMap.values()) {
            if (pushCategory(settings.representedObject.size))
                return true;
        }
        return false;
    }
};

WI.FolderizedTreeElement.MediumChildCountThreshold = 5;
WI.FolderizedTreeElement.LargeChildCountThreshold = 15;
WI.FolderizedTreeElement.NumberOfMediumCategoriesThreshold = 2;
WI.FolderizedTreeElement.NewChildQueueUpdateInterval = 500;
