/*
 * ADOBE CONFIDENTIAL
 *
 * Copyright (c) 2015 Adobe Systems Incorporated. All rights reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Adobe Systems Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Adobe Systems Incorporated and its
 * suppliers and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Adobe Systems Incorporated.
 */

/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, bitwise: true, node: true */
/*global require: true, $: true, exports: true, csInterface: true*/

(function () {
    "use strict";
    
    var _  = require("underscore");

    var DocinfoUtils = function () {};

    DocinfoUtils.prototype.visitLayers = function (root, visitorFunction, results) {
        results = results || [];
        if (root && root.layers) {
            root.layers.forEach(function (layer) {
                // If the visitor function returns false, don't visit the children of the layer.
                var result = visitorFunction(layer);
                if (result === false) {
                    return;
                }

                results.push(result);
                this.visitLayers(layer, visitorFunction, results);
            }.bind(this));
        }
        return results;
    };

    /**
     * Returns each selected layer, except if the layer's siblings are all selected. In other words, if the user
     * selects a group and all of its children are also selected, we only export the group. If only some of the group's
     * children are selected, we export both the selected group and the selected children.
     *
     * @param {Object} docinfo
     * @return {Array} An array of layers.
     */
    DocinfoUtils.prototype.getSelectedLayersForExport = function (docinfo) {
        // Put the selected layer ids in a hash map for quick lookups.
        var selectedLayerIdsMap = {};
        docinfo._selectionById.forEach(function (selectedLayerId) {
            selectedLayerIdsMap[selectedLayerId] = true;
        });

        // Visit each layer and add it to the array if it's selected.
        var selectedLayers = [];
        this.visitLayers(docinfo, function (layer) {
            var layerIsSelected = selectedLayerIdsMap[layer.id];
            if (layerIsSelected) {
                selectedLayers.push(layer);

                // If all of this selected layer's children are also selected, do not visit them.
                return !this._allChildrenAreSelected(layer, selectedLayerIdsMap);
            }

            // Visit the children.
            return true;
        }.bind(this));
        return selectedLayers;
    };

    DocinfoUtils.prototype._allChildrenAreSelected = function (parentLayer, selectedLayerIdsMap) {
        return _(parentLayer.layers).every(function (childLayer) {
            return selectedLayerIdsMap[childLayer.id];
        });
    };

    /**
     * See if the document has artboards. If so, return an array of them; if not, return an empty array.
     * @param {Object} docinfo
     * @return {Array} An array of layers.
     */
    DocinfoUtils.prototype.getArtboards = function (docinfo) {
        // Artboards will be at the top level if they exist.
        return _(docinfo.layers).filter(function (layer) {
            return !!layer.artboard;
        });
    };

    module.exports = new DocinfoUtils();
}());
