/* <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;
var Component = require("montage/ui/component").Component;
var Collapser = require("js/panels/Timeline/Collapser").Collapser;
var Hintable = require("js/components/hintable.reel").Hintable;
var LayerStyle = require("js/panels/Timeline/Style.reel").LayerStyle;
var DynamicText = require("montage/ui/dynamic-text.reel").DynamicText;
var defaultEventManager = require("montage/core/event/event-manager").defaultEventManager;
var nj = require("js/lib/NJUtils").NJUtils;

var Layer = exports.Layer = Montage.create(Component, {

    hasTemplate:{
        value: true
    },
    
    /* Begin: Models */
   
	/* Main collapser model: the main collapser for the layer */
    _mainCollapser : {
    	value: false
    },
    mainCollapser: {
    	get: function() {
    		return this._mainCollapser;
    	},
    	set: function(newVal) {
    		this._mainCollapser = newVal;
    	}
    },
    
    /* Style models: the array of styles, and the repetition that uses them */
    _arrLayerStyles : {
    	serializable: true,
		enumerable: true,
	    value: []
    },
    arrLayerStyles : {
    	serializable: true,
        enumerable: true,
    	get: function() {
    		return this._arrLayerStyles;
    	},
    	set: function(newVal) {
    		this._arrLayerStyles = newVal;
    	}
    },
    _styleRepetition : {
    	value: false
    },
    styleRepetition : {
    	get: function() {
    		return this._styleRepetition;
    	},
    	set: function(newVal) {
    		this._styleRepetition = newVal;
    	}
    },
    _styleCounter : {
    	value: 0
    },

	/* Layer models: the name, ID, and selected and animation booleans for the layer */
    _layerName:{
    	serializable: true,
        value:null,
        writable:true,
        enumerable:true
    },
    
    layerName:{
    	serializable: true,
        get:function(){
            return this._layerName;
        },
        set:function(newVal){
        	if (newVal !== this._layerName) {
        		this._layerEditable.value = newVal;
	        	this._layerName = newVal;
	        	this.layerData.layerName = newVal;
	        	this.log('layerName setter: ' + newVal)
        	}
        	
        }
    },
    _layerID:{
        value:null,
        writable:true,
    	serializable: true,
        enumerable:true
    },

    layerID:{
    	serializable: true,
        get:function(){
            return this._layerID;
        },
        set:function(value){
            this._layerID = value;
        }
    },
    
    /* Position and Transform hottext values */
    _dtextPositionX : {
        value:null,
    	serializable: true
    },

    dtextPositionX:{
    	serializable: true,
        get:function(){
            return this._dtextPositionX;
        },
        set:function(value){
        	if (this._dtextPositionX !== value) {
        		this._dtextPositionX = value;
        		//this.needsDraw = true;
        	}
            
        }
    },
    
    _dtextPositionY : {
        value:null,
    	serializable: true
    },

    dtextPositionY:{
    	serializable: true,
        get:function(){
            return this._dtextPositionY;
        },
        set:function(value){
        	if (this._dtextPositionY !== value) {
        		this._dtextPositionY = value;
        		//this.needsDraw = true;
        	}
            
        }
    },
    
    _dtextScaleX : {
        value:null,
    	serializable: true
    },

    dtextScaleX:{
    	serializable: true,
        get:function(){
            return this._dtextScaleX;
        },
        set:function(value){
        	if (this._dtextScaleX !== value) {
        		this._dtextScaleX = value;
        		//this.needsDraw = true;
        	}
            
        }
    },
    
    _dtextScaleY : {
        value:null,
    	serializable: true
    },

    dtextScaleY:{
    	serializable: true,
        get:function(){
            return this._dtextScaleY;
        },
        set:function(value){
        	if (this._dtextScaleY !== value) {
        		this._dtextScaleY = value;
        		//this.needsDraw = true;
        	}
            
        }
    },
    
    _dtextSkewX : {
        value:null,
    	serializable: true
    },

    dtextSkewX:{
    	serializable: true,
        get:function(){
            return this._dtextSkewX;
        },
        set:function(value){
        	if (this._dtextSkewX !== value) {
        		this._dtextSkewX = value;
        		//this.needsDraw = true;
        	}
            
        }
    },
    
    _dtextSkewY : {
        value:null,
    	serializable: true
    },

    dtextSkewY:{
    	serializable: true,
        get:function(){
            return this._dtextSkewY;
        },
        set:function(value){
        	if (this._dtextSkewY !== value) {
        		this._dtextSkewY = value;
        		//this.needsDraw = true;
        	}
            
        }
    },
    
    _dtextRotate : {
        value:null,
    	serializable: true
    },

    dtextRotate:{
    	serializable: true,
        get:function(){
            return this._dtextRotate;
        },
        set:function(value){
        	if (this._dtextRotate !== value) {
        		this._dtextRotate = value;
        		//this.needsDraw = true;
        	}
            
        }
    },
    
    /* isSelected: whether or not the layer is currently selected. */
    _isSelected:{
        value: false,
        writable: true,
        serializable: true,
        enumerable: false
    },

    isSelected:{
        get:function(){
            return this._isSelected;
        },
        set:function(value){
        	if (value !== this._isSelected) {
        		// Only concerned about different values
        		if (value === false) {
        			// If changing from true to false, we need to deselect any associated styles
        			this.selectStyle(false);
        		}
        		this._isSelected = value;
        		this.layerData.isSelected = value;
        		this.needsDraw = true;
        	}
            
        }
    },
    
    /* isActive:  Whether or not the user is actively clicking within the layer; used to communicate state with
     * TimelinePanel.
     */
    _isActive: {
    	value: false
    },
    isActive: {
    	get: function() {
    		return this._isActive;
    	},
    	set: function(newVal) {
    		this._isActive = newVal;
    	}
    },
    
    
    _isAnimated:{
        value: false,
        writable: true,
        enumerable: false
    },

    isAnimated:{
        get:function(){
            return this._isAnimated;
        },
        set:function(value){
            this._isAnimated = value;
        }
    },
    _justAdded: {
    	value: false
    },
    _layerEditable : {
    	value: false
    },
    
    // Are the various collapsers collapsed or not
    _isMainCollapsed : {
    	serializable: true,
    	value: true
    },
    isMainCollapsed : {
    	serializable: true,
    	get: function() {
    		return this._isMainCollapsed;
    	},
    	set: function(newVal) {
    		this.log('layer.js: isMainCollapsed: ' + newVal);
    		if (newVal !== this._isMainCollapsed) {
    			this._isMainCollapsed = newVal;
    		}
    	}
    },
    
    _isTransformCollapsed : {
    	serializable: true,
    	value: true
    },
    isTransformCollapsed : {
    	serializable: true,
    	get: function() {
    		return this._isTransformCollapsed;
    	},
    	set: function(newVal) {
    		if (newVal !== this._isTransformCollapsed) {
    			this._isTransformCollapsed = newVal;
    			//this.needsDraw = true;
    		}
    	}
    },
    
    _isPositionCollapsed : {
    	serializable: true,
    	value: true
    },
    isPositionCollapsed : {
    	serializable: true,
    	get: function() {
    		return this._isPositionCollapsed;
    	},
    	set: function(newVal) {
    		if (newVal !== this._isPositionCollapsed) {
    			this._isPositionCollapsed = newVal;
    			//this.needsDraw = true;
    		}
    	}
    },
    
    _isStyleCollapsed : {
    	serializable: true,
    	value: true
    },
    isStyleCollapsed : {
    	serializable: true,
    	get: function() {
    		return this._isStyleCollapsed;
    	},
    	set: function(newVal) {
    		if (newVal !== this._isStyleCollapsed) {
    			this._isStyleCollapsed = newVal;
    			//this.needsDraw = true;
    		}
    	}
    },
    _bypassAnimation : {
    	serializable: true,
    	value: false
    },
    bypassAnimation : {
    	serializable: true,
    	get: function() {
    		return this._bypassAnimation;
    	},
    	set: function(newVal) {
    		this._bypassAnimation = newVal;
    	}
    },

    _layerData:{
        serializable:true,
        value:{}
    },

    layerData:{
        serializable:true,
        get:function(){
            return this._layerData;
        },
        set:function(val){
            this._layerData = val;
            if(this._layerData){
                this.setData();
            }
        }
    },

    setData:{
        value:function(){
            this.layerName = this.layerData.layerName;
            this.layerID = this.layerData.layerID;
            this.arrLayerStyles = this.layerData.arrLayerStyles;
            this.isMainCollapsed = this.layerData.isMainCollapsed;
            this.isPositionCollapsed = this.layerData.isPositionCollapsed;
            this.isTransformCollapsed = this.layerData.isTransformCollapsed;
            this.isSelected = this.layerData.isSelected;
            this.isActive = this.layerData.isActive;
            this.isStyleCollapsed = this.layerData.isStyleCollapsed;
            this.bypassAnimation = this.layerData.bypassAnimation;
            this.dtextPositionX = this.layerData.dtextPositionX;
            this.dtextPositionY = this.layerData.dtextPositionY;
            this.dtextSkewX = this.layerData.dtextSkewX;
            this.dtextSkewY = this.layerData.dtextSkewY;
            this.dtextScaleX = this.layerData.dtextScaleX;
            this.dtextScaleY = this.layerData.dtextScaleY;
            this.dtextRotate = this.layerData.dtextRotate;
            this._isFirstDraw = this.layerData._isFirstDraw;
            this.needsDraw = true;
        }
    },
    _isFirstDraw : {
    	value: true
    },

	/* END: Models */

	/* Begin: Draw cycle */
    prepareForDraw: {
        value: function() {
        	
        	// Initialize myself
			this.init();
			
        	var that = this;

        	// Make it editable!
        	this._layerEditable = Hintable.create();
        	this._layerEditable.element = this.titleSelector;
        	this.titleSelector.identifier = "selectorEditable";
        	this.titleSelector.addEventListener("click", this, false);
        	this._layerEditable.addEventListener("blur", function(event) {
        		that.handleSelectorEditableBlur(event);
        	}, false);
        	this._layerEditable.addEventListener("change", function(event) {
				that.dynamicLayerName.value = that._layerEditable.value;
				that.needsDraw = true;
        	}, false);
        	this._layerEditable.editingClass = "editable2";
        	this._layerEditable.value = this.layerName;
        	this._layerEditable.needsDraw = true;

            this.mainCollapser.clicker.addEventListener("click", this.handleMainCollapserClick.bind(this), false);
            this.positionCollapser.clicker.addEventListener("click", this.handlePositionCollapserClick.bind(this), false);
            this.transformCollapser.clicker.addEventListener("click", this.handleTransformCollapserClick.bind(this), false);
            this.styleCollapser.clicker.addEventListener("click", this.handleStyleCollapserClick.bind(this), false);


            // Add event listeners to add and delete style buttons
            this.buttonAddStyle.identifier = "addStyle";
            this.buttonAddStyle.addEventListener("click", this, false);
            
            this.buttonDeleteStyle.identifier = "deleteStyle";
            this.buttonDeleteStyle.addEventListener("click", this, false);
            
            // Add mousedown listener to set isActive
            this.element.addEventListener("mousedown", this, false);
            this.element.addEventListener("click", this, false);

        }
    },
    draw: {
    	value: function() {
            if (this.isSelected) {
            	this.element.classList.add("selected");
            } else {
            	this.element.classList.remove("selected");
            }
    	}
    },
    didDraw: {
    	value: function() {
    		if ((this.isSelected === true) && (this._isFirstDraw === true)) {
    			// Once we're done drawing the first time we need to tell the TimelinePanel if
    			// this layer is supposed to be selected.
    			this.parentComponent.parentComponent.selectedLayerID = this.layerID;
    			this._isFirstDraw = false;
    		}
    	}
    },
	/* End: Draw cycle */
	
	/* Begin: Controllers */
	
	// Initialize a just-created layer with some basic defaults and needed selectors.
	init: {
		value: function() {
			// Default some vars
			//this.arrLayerStyles = [];
			
			// Get some selectors.
        	this.label = this.element.querySelector(".label-layer");
        	this.titleSelector = this.label.querySelector(".collapsible-label");
        	this.buttonAddStyle = this.element.querySelector(".button-add");
        	this.buttonDeleteStyle = this.element.querySelector(".button-delete");

		}
	},
    selectLayer:{
        value:function(){
            // this.mainCollapser.header.classList.add("layerSelected");
            this.element.classList.add("layerSelected");
            this.isSelected = true;
        }
    },
    deselectLayer:{
        value:function(){
            // this.mainCollapser.header.classList.remove("layerSelected");
            this.element.classList.remove("layerSelected");
            this.isSelected = false;
        }
    },
	addStyle : {
		value: function() {
			// Add a new style rule.  It should be added above the currently selected rule, 
			// Or at the end, if no rule is selected.

			var newLength = 0, 
				mySelection = 0,
				// newStyle = LayerStyle.create(),
				newStyle = {},
				newEvent = document.createEvent("CustomEvent");
			
			this.isStyleCollapsed = false;
			
			newEvent.initCustomEvent("layerEvent", false, true);
			newEvent.layerEventLocale = "styles";
			newEvent.layerEventType = "newStyle";
			newEvent.layerID = this.layerID;
			newEvent.styleID = this.layerID + "@" + this._styleCounter;
			
			newStyle.styleID = newEvent.styleID;
			newStyle.whichView = "hintable";
			newStyle.editorProperty = "";
			newStyle.editorValue = "";
			newStyle.ruleTweener = false;
			newStyle.isSelected = false;

			if (!!this.styleRepetition.selectedIndexes) {
				mySelection = this.styleRepetition.selectedIndexes[0];
				this.arrLayerStyles.splice(mySelection, 0, newStyle);
				//this.styleRepetition.selectedIndexes = [mySelection];
				this.selectStyle(mySelection);
			} else {
				newLength = this.arrLayerStyles.length;
				this.arrLayerStyles.push(newStyle);
				mySelection = this.arrLayerStyles.length;
				// this.styleRepetition.selectedIndexes = [mySelection-1];
				this.selectStyle(mySelection-1);
			}
			
			// Set up the event info and dispatch the event

			newEvent.styleSelection = mySelection;
			//defaultEventManager.dispatchEvent(newEvent);

		}
	},
	deleteStyle : {
		value: function() {
			var newEvent = document.createEvent("CustomEvent"),
				selectedIndex = 0;
			if (this.arrLayerStyles.length > 0) {
				if (!!this.styleRepetition.selectedIndexes) {
					
					selectedIndex = this.styleRepetition.selectedIndexes[0];

					// Set up the event info and dispatch the event
					newEvent.initCustomEvent("layerEvent", false, true);
					newEvent.layerEventLocale = "styles";
					newEvent.layerEventType = "deleteStyle";
					newEvent.layerID = this.layerID;
					newEvent.styleID = this.arrLayerStyles[selectedIndex].styleID;
					newEvent.styleSelection = selectedIndex;
					//defaultEventManager.dispatchEvent(newEvent);
					
					// Delete the style from the view
					this.arrLayerStyles.splice(selectedIndex, 1);
					
					// Was that the last style?
					if (this.arrLayerStyles.length === 0) {
						this.buttonDeleteStyle.classList.add("disabled");
					}
					
				}
			}
		}
	},
	selectStyle : {
		value: function(styleIndex) {

    		// Select a style based on its index.
    		// use layerIndex = false to deselect all styles.
    		var i = 0,
    			arrLayerStylesLength = this.arrLayerStyles.length;

    		// First, update this.arrStyles[].isSelected
    		for (i = 0; i < arrLayerStylesLength; i++) {
    			if (i === styleIndex) {
    				this.arrLayerStyles[i].isSelected = true;
    			} else {
    				this.arrLayerStyles[i].isSelected = false;
    			}
    		}
    		
    		// Next, update this.styleRepetition.selectedIndexes.
    		if (styleIndex !== false) {
    			this.styleRepetition.selectedIndexes = [styleIndex];
    			this.buttonDeleteStyle.classList.remove("disabled");
    		} else {
    			this.styleRepetition.selectedIndexes = null;
    			if (typeof(this.buttonDeleteStyle) !== "undefined") {
    				this.buttonDeleteStyle.classList.add("disabled");
    			}
    		}
			
		}
	},
    getActiveStyleIndex : {
    	value: function() {
    		// Searches through the styles and looks for one that has
    		// set its isActive flag to true.
    		var i = 0, 
    			returnVal = false,
    			arrLayerStylesLength = this.arrLayerStyles.length;
    		
    		for (i = 0; i < arrLayerStylesLength; i++) {
    			if (this.arrLayerStyles[i].isActive === true) {
    				returnVal = i;
    				this.arrLayerStyles[i].isActive = false;
    			}
    		}
    		return returnVal;
    	}
    },
	/* End: Controllers */
    
	/* Begin: Event handlers */
	handleAddStyleClick: {
		value: function(event) {
			this.addStyle();
		}
	},
	handleDeleteStyleClick: {
		value: function(event) {
			this.deleteStyle();
		}
	},
	handleSelectorEditableClick: {
		value: function(event) {
		}
	},
	handleSelectorEditableBlur : {
		value: function(event) {
        	this.titleSelector.scrollLeft = 0;
		}
	},
	handleSelectorEditableChange: {
		value: function(event) {
			this.layerName = this.dynamicLayerName.value;
			this.needsDraw = true;
		}
	},
	handleMousedown: {
		value: function(event) {
			this.layerData.isActive = true;
			var ptrParent = nj.queryParentSelector(event.target, ".content-style");
			if (ptrParent !== false) {
				this.selectStyle(this.getActiveStyleIndex());
			}
		}
	},
	handleLayerClick : {
		value: function(event) {
			var ptrParent = nj.queryParentSelector(event.target, ".content-style");
			if (ptrParent !== false) {
				var myIndex = this.getActiveStyleIndex();
				this.selectStyle(myIndex);
			}
		}
	},
	handleMainCollapserClick : {
		value: function(event) {
			this.mainCollapser.bypassAnimation = false;
			this.bypassAnimation = false;
			if (this.isMainCollapsed) {
				this.isMainCollapsed = false;
			} else {
				this.isMainCollapsed = true;
			}
		}
	},
	handlePositionCollapserClick : {
		value: function(event) {
			this.positionCollapser.bypassAnimation = false;
			this.bypassAnimation = false;
			if (this.isPositionCollapsed) {
				this.isPositionCollapsed = false;
			} else {
				this.isPositionCollapsed = true;
			}
		}
	},
	handleTransformCollapserClick : {
		value: function(event) {
			this.transformCollapser.bypassAnimation = false;
			this.bypassAnimation = false;
			if (this.isTransformCollapsed) {
				this.isTransformCollapsed = false;
			} else {
				this.isTransformCollapsed = true;
			}
		}
	},
	handleStyleCollapserClick : {
		value: function(event) {
			this.styleCollapser.bypassAnimation = false;
			this.bypassAnimation = false;
			if (this.isStyleCollapsed) {
				this.isStyleCollapsed = false;
			} else {
				this.isStyleCollapsed = true;
			}
		}
	},
	/* End: Event handlers */
	
	/* Begin: Logging routines */
    _boolDebug: {
    	enumerable: false,
    	value: false // set to true to enable debugging to console; false for turning off all debugging.
    },
    boolDebug: {
    	get: function() {
    		return this._boolDebug;
    	},
    	set: function(boolDebugSwitch) {
    		this._boolDebug = boolDebugSwitch;
    	}
    },
    log: {
    	value: function(strMessage) {
    		if (this.boolDebug) {
    			console.log(this.getLineNumber() + ": " + strMessage);
    		}
    	}
    },
    getLineNumber: {
    	value: function() {
			try {
			   throw new Error('bazinga')
			}catch(e){
				return e.stack.split("at")[3].split(":")[2];
			}
    	}
    }
	/* End: Logging routines */

});