/* <copyright>
 This file contains proprietary software owned by Motorola Mobility, Inc.<br/>
 No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.<br/>
 (c) Copyright 2011 Motorola Mobility, Inc.  All Rights Reserved.
 </copyright> */
/**
 @module montage/ui/controller/tree-controller
 @requires montage/core/core
 @requires montage/ui/controller/object-controller
 @requires montage/core/event/mutable-event
 */
var Montage = require("montage").Montage,
    ObjectController = require("montage/ui/controller/object-controller").ObjectController,
    ArrayController = require("montage/ui/controller/array-controller").ArrayController,
    MutableEvent = require("montage/core/event/mutable-event").MutableEvent;
/**
    TODO: Write description like the array controllers: The ArrayController helps with organizing a hierarchical
    collection of objects, and managing user selection within that collection.
    You can assign a TreeController instance as the <code>contentProvider</code> property for a TreeView object.
    @class module:montage/ui/controller/tree-controller.TreeController
    @classdesc
    @extends module:montage/ui/controller/object-controller.ObjectController
*/
var TreeController = exports.TreeController = Montage.create(ObjectController, /** @lends module:montage/ui/controller/tree-controller.TreeController# */ {

    rootKey : {
        value: null
    },

    branchKey : {
        value: null
    },

    _root : {
        value : null
    },
    root : {
        get: function() {
            return this._root;
        },
        set: function(value) {
            this._root = value;

            this.initArrayControllers();
        }
    },

    rootController: {
        value: null
    },

    initArrayControllers : {
        value: function() {
            var self = this;

            ///// Recursive function that finds all branch nodes and initializes
            ///// sets the tree node type to "branch" or "leaf"

            function walk(node, init, depth) {
                var branch = node[self.branchKey];

                if(branch) {
                    branch.forEach(function(node) {
                        walk(node, init, ++depth);
                    });

                    node['treeNodeType'] = 'branch';
                } else {
                    node['treeNodeType'] = 'leaf';
                }
            }

            walk(this._root, 0);

        }
    },

    /**
        @private
     */
    _selectedIndexes: {
        value: null,
        enumerable: false
    },

   /**
        Description TODO
        @type {Function}
        @default null
    */
   selectedIndexes: {
       get: function() {
           return this._selectedIndexes;
       },
       set: function(value) {
           this._selectedIndexes = value;
       }
   },

    branchControllers: {
        value: [],
        distinct: true
    },

    addBranchController : {
        value: function(controller) {
            if(this.delegate) {
                controller.delegate = this.delegate;
            }

            this.branchControllers.push(controller);
        }
    },

    /**
     @private
     */
    _content: {
        enumerable: false,
        value: null
    },
    /**
        The content managed by the TreeController.
        @type {Function}
        @default {String} null
    */
    content: {
        get: function() {
            return this._content;
        },
        set: function(value) {
            if (this._content === value) {
                return;
            }

            this._content = value;

            this.selectedObjects = null;

            if (this.rootKey) {
                if (value[this.rootKey]) {
                    this.root = value[this.rootKey];
                } else {
                    console.log('No root key found in content data');
                }
            } else {
                this.root = value;
            }

        }
    },

    addObjects : {
        value: function() {

            var objects = Array.prototype.slice.call(arguments),
                i,
                objectCount = objects.length,
                selectedContentIndexes, firstIndex;

            for (i = 0; i < objectCount; i++) {
                this.content.push(objects[i]);
            }

            if (this.selectObjectsOnAddition) {
                selectedContentIndexes = [];
                firstIndex = this.content.length-objectCount;
                for (i = 0; i < objectCount; i++) {
                    selectedContentIndexes[i] = firstIndex++;
                }
                this.selectedContentIndexes = selectedContentIndexes;
                this.selectedObjects = objects;
            }

            if (this.clearFilterFunctionOnAddition) {
                this.filterFunction = null;
            }

            if (this.automaticallyOrganizeObjects) {
                this.organizeObjects();
            }

        }
    }

});