/* <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> */


var Montage = require("montage/core/core").Montage,
    Component = require("montage/ui/component").Component;

exports.SelectionController = Montage.create(Component, {

    _isDocument: {
        value: true
    },

    isDocument: {
        get: function() {
            return this._isDocument;
        }
    },

    _currentDocument: {
            value : null
    },

    currentDocument : {
        get : function() {
            return this._currentDocument;
        },
        set : function(value) {
            if (value === this._currentDocument) {
                return;
            }

            if(this._currentDocument && this._currentDocument.currentView === "design") {
                this._currentDocument.model._selection = this.application.ninja.selectedElements;
            }

            this._currentDocument = value;

            if(this._currentDocument && this._currentDocument.currentView === "design") {
                this.selectedElements = this._currentDocument.model.selection;
            }
            /*
            if(!value) {
            } else if(this._currentDocument.currentView === "design") {
            } else {
            }
            */

        }
    },

    _selectedElements: {
        value: null
    },

    selectedElements: {
        get: function() {
            return this._selectedElements;
        },
        set: function(value) {

            if(value) {
                this._selectedElements = value;

                this.application.ninja.selectedElements = this._selectedElements;

                if(this._selectedElements.length === 0) {
                    this.executeSelectElement();
                } else {
                    this.executeSelectElement(this._selectedElements);
                }
            }
        }
    },

    deserializedFromTemplate: {
        value: function() {
            this.eventManager.addEventListener("elementAdded", this, false);
            this.eventManager.addEventListener("elementsRemoved", this, false);
            this.eventManager.addEventListener("elementReplaced", this, false);
            this.eventManager.addEventListener("selectAll", this, false);
        }
    },

    handleElementAdded: {
        value: function(event) {
            this.executeSelectElement(event.detail);
        }
    },

    handleElementsRemoved: {
        value: function(event) {
            if(!this._isDocument) {
                this.application.ninja.selectedElements = [];
                this._isDocument = true;
                NJevent("selectionChange", {"elements": this.application.ninja.selectedElements, "isDocument": this._isDocument});
            }
        }
    },

    handleElementReplaced: {
        value: function(event) {
            this.application.ninja.selectedElements[this.application.ninja.selectedElements.indexOf(event.detail.data.oldChild)] = event.detail.data.newChild;
        }
    },

    handleSelectAll: {
        value: function(event) {
            var selected = [], childNodes = [], self = this;

            childNodes = this.currentDocument.model.domContainer.childNodes;
            childNodes = Array.prototype.slice.call(childNodes, 0);
            childNodes.forEach(function(item) {
                if(self.isNodeTraversable(item)) {
                    selected.push(item);
                }
            });

            this.selectElements(selected);
        }
    },

    /**
     * Select Element. This function will not check that element, it will simply add it to the selection array.
     */
    executeSelectElement: {
        value: function(element) {
            this.application.ninja.selectedElements = [];

            if(element) {
                if(Array.isArray(element)) {
                    this.application.ninja.selectedElements = Array.prototype.slice.call(element, 0);
                } else {
                    this.application.ninja.selectedElements.push(element);
                }
                this._isDocument = false;
            } else {
                this._isDocument = true;
            }

            NJevent("selectionChange", {"elements": this.application.ninja.selectedElements, "isDocument": this._isDocument} );

        }

    },

    selectElement: {
        value: function(element) {
            if(this.findSelectedElement(element) === -1) {

                if(this.application.ninja.currentDocument.inExclusion(element) !== -1){
                    if(this.isDocument) return;     // If the stage is already selected do nothing.
                    this.executeSelectElement();    // Else execute selection with no element
                } else {
                    if(element.parentNode.uuid === this.currentDocument.model.domContainer.uuid) {
                        this.executeSelectElement(element);
                    } else {
                        var outerElement = element.parentNode;

                        while(outerElement.parentNode && outerElement.parentNode.uuid !== this.currentDocument.model.domContainer.uuid) {
                            // If element is higher up than current container then return
                            if(outerElement.nodeName === "BODY") return;
                            // else keep going up the chain
                            outerElement = outerElement.parentNode;
                        }

                        this.executeSelectElement(outerElement);
                    }
                }
            }
        }
    },

    selectElements: {
        value: function(elements) {
            if(elements && elements.length > 0) {
                var that = this;
                this.application.ninja.selectedElements = [];

                elements.forEach(function(element) {
                    that.application.ninja.selectedElements.push(element);
                    that._isDocument = false;
                });

                NJevent("selectionChange", {"elements": this.application.ninja.selectedElements, "isDocument": this._isDocument} );
            }
        }
    },

    shiftSelectElement: {
        value: function(element) {
            if(this.application.ninja.currentDocument.inExclusion(element) !== -1) return;

            (this.findSelectedElement(element) !== -1 ) ? this.removeElement(element) : this.insertElement(element);
        }
    },

    insertElement: {
        value: function(element) {
            if(element) {
                if(this._isDocument) {
                    this.application.ninja.selectedElements = [];
                    this._isDocument = false;
                }

                this.application.ninja.selectedElements.push(element);

                NJevent("selectionChange", {"elements": this.application.ninja.selectedElements, "isDocument": this._isDocument} );
            }
        }
    },

    removeElement: {
        value: function(item) {
            if(item){
                try{
                    if(this.application.ninja.selectedElements.length > 1) {
                        var idx = this.findSelectedElement(item);
                        if(idx != -1){
                            this.application.ninja.selectedElements.splice(idx, 1);
                        }
                    } else {
                        this.application.ninja.selectedElements = [];
                        this._isDocument = true;
                    }

                    NJevent("selectionChange", {"elements": this.application.ninja.selectedElements, "isDocument": this._isDocument} );

                } catch (err) {
                    console.log("Fault: " + err);
                }
            }

        }
    },

	isObjectSelected: {
		value: function( elt ) {
			return this.findSelectedElement(elt) > -1;
		}
	},

    findSelectedElement: {
        value: function(item) {
            // TODO: Remove this function and use the stage selectable. Then only return a match in the array
            //return this.application.ninja.selectedElements.indexOf(item);

            //TODO: Make sure we don't need to loop back to the container element.
            var itemUUID;

            for(var i=0, uuid; this.application.ninja.selectedElements[i];i++) {
                // Check for multiple selection and excluding inner elements
                if(item.parentNode && item.parentNode !== this.application.ninja.currentDocument.model.documentRoot) {
                    var outerElement = item.parentNode;

                    while(outerElement.parentNode && outerElement.parentNode !== this.application.ninja.currentDocument.model.documentRoot) {
                        outerElement = outerElement.parentNode;
                    }

                    itemUUID = outerElement.uuid;
                } else {
                    itemUUID = item.uuid;
                }

                if(this.application.ninja.selectedElements[i].uuid === itemUUID) {
                    return i;
                }
            }

            return -1;
        }
    },

    isNodeTraversable: {
        value: function( item ) {
            if(item.nodeType !== 1) return false;
            return ((item.nodeName !== "STYLE") && (item.nodeName !== "SCRIPT"));
        }
    }

});