var Montage = require("montage/core/core").Montage;
var Component = require("montage/ui/component").Component;
var Layer = require("js/panels/Timeline/Layer.reel").Layer;
var TimelineTrack = require("js/panels/Timeline/TimelineTrack.reel").TimelineTrack;
var nj = require("js/lib/NJUtils").NJUtils;

// var Track = require("js/panels/Timeline/Track.reel").Track;

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

    hasTemplate: {
        value: true
    },
   
    /* === BEGIN: Models === */
   
    // Layer models: arrays for the data and repetition,  current layer number,
    _arrLayers : {
        value: []
    },
    arrLayers: {
        get: function() {
            return this._arrLayers;
        },
        set: function(newVal) {
            this._arrLayers = newVal;
        }
    },
   
    _layerRepetition: {
        value: null
    },
    layerRepetition: {
        get: function() {
            return this._layerRepetition;
        },
        set: function(newVal) {
            this._layerRepetition = newVal;
        }
    },
   
    currentLayerNumber:{
        value:0
    },

    millisecondsOffset:{
        value:5000
    },

    // Track model
    _arrTracks: {
        serializable: true,
        value: []
    },
    arrTracks: {
        serializable: true,
        get: function() {
            return this._arrTracks;
        },
        set: function(newVal) {
            this._arrTracks = newVal;
        }
    },
    _trackRepetition: {
        serializable: true,
        value: null
    },
    trackRepetition : {
        serializable: true,
        get: function() {
            return this._trackRepetition;
        },
        set: function(newVal) {
            this._trackRepetition = newVal;
        }
    },

    _selectedKeyframes:{
        value:[]
    },

    selectedKeyframes:{
        serializable:true,
        get:function () {
            return this._selectedKeyframes;
        },
        set:function (newVal) {
            this._selectedKeyframes = newVal;
        }
    },


    /* === END: Models === */
   
    /* === BEGIN: Draw cycle === */

    prepareForDraw: {
        value: function() {

            this.eventManager.addEventListener("deleteLayerClick", this, false);
            this.eventManager.addEventListener("newLayer", this, false);
            this.eventManager.addEventListener("deleteLayer", this, false);
            this.eventManager.addEventListener( "layerBinding", this, false);
            this.eventManager.addEventListener("elementAdded", this, false);
            this.eventManager.addEventListener("elementDeleted", this, false);
            this.eventManager.addEventListener("deleteSelection", this, false);
            this.hashInstance=this.createLayerHashTable();
            this.hashTrackInstance=this.createTrackHashTable();
            this.initTimelineView();
        }
    },

    _isLayer: {
        value: false
    },

    _isLayerAdded:{
        value:false
    },

    addButtonClicked:{
        value:true
    },

    _firstLayerDraw:{
        value:false,
        writable:true
    },

    willDraw: {
        value: function() {
            if (this._isLayer) {
                this.addButtonClicked=false;
                this._isElementAdded=true;
                NJevent('newLayer',this)
                this._isLayer = false;
                this.addButtonClicked=true;
            }
        }
    },

    /* === END: Draw cycle === */

    /* === BEGIN: Controllers === */
   
    // Initialize the timeline
    initTimelineView : {
        value:function(){
        	
        	// Get some selectors to make life easier.
        	this.layout_tracks = this.element.querySelector(".layout-tracks");
        	this.layout_markers = this.element.querySelector(".layout_markers");

            // Add event handlers on the buttons.
            this.newlayer_button.identifier = "addLayer";
            this.newlayer_button.addEventListener("click", this, false);
            this.deletelayer_button.identifier = "deleteLayer";
            this.deletelayer_button.addEventListener("click", this, false);
            
            // New click listener to handle select/deselect events
            this.timeline_leftpane.addEventListener("click", this.timelineLeftPaneClick.bind(this), false);
            
            // New click listener on body to handle "blurring" the panel
            document.addEventListener("click", this.handleBlur.bind(this), false);

            // Simultaneous scrolling of the layer and tracks
            this.layout_tracks.addEventListener("scroll", this.updateLayerScroll.bind(this), false);
            this.user_layers.addEventListener("scroll", this.updateLayerScroll.bind(this), false);

            // Calculate and draw time markers
            this.drawTimeMarkers();

            // Default to one layer for new doc
//            this.newLayer();
            this._hashKey="123";
            _firstLayerDraw = false;
            NJevent('newLayer',this._hashKey);
            _firstLayerDraw = true;

            // TODO - add condition for existing doc and parse DOM for top level elements
        }
    },

    updateLayerScroll:{
        value:function(){
        	console.log(this.layout_tracks.scrollLeft)
            this.user_layers.scrollTop = this.layout_tracks.scrollTop;
            this.layout_markers.scrollLeft = this.layout_tracks.scrollLeft;
        }
    },

    deselectKeyframes:{
        value:function () {
            for (var i = 0; i < this.selectedKeyframes.length; i++) {
                this.selectedKeyframes[i].deselect();
            }
            this.selectedKeyframes = null;
            this.selectedKeyframes = new Array();
        }
    },

    handleAddLayerClick:{
        value:function(event){
            //event.stopPropagation();
            this._isLayer = true;
            this.needsDraw = true;

        }
    },

    handleDeleteLayerClick:{
        value:function(event){
            //event.stopPropagation();
            this._deleteKeyDown=false;
            if(this.application.ninja.currentSelectedContainer.id==="UserContent"){
                this._hashKey="123";
            }
            NJevent('deleteLayer')
        }
    },

    handleLayerBinding:{
        value:function(event){
             var i=0;
             this.currentParentNode=this.application.ninja.currentSelectedContainer.parentNode;
             this.removeLayerFromParentUUid = this.application.ninja.currentSelectedContainer.parentNode.uuid;
             this.currentElement= event.detail.element;

//             if(this._firstLayerDraw===false){
//                 while(this.arrLayers.pop()){
//                 }
//                 while(this.arrTracks.pop()){
//                 }
//             }

             this._hashKey = event.detail.element.uuid;
             if(this.returnedObject = this.hashInstance.getItem(this._hashKey)){
                this.returnedTrack = this.hashTrackInstance.getItem(this._hashKey);
                this._hashFind = true;
                NJevent('newLayer');

            }

        }
    },

	timelineLeftPaneClick : {
		value: function(event) {
			// Check ALL THE CLICKS
			// Are they in a particular layer? If so, we need to select that layer and
			// deselect the others.
			var ptrParent = nj.queryParentSelector(event.target, ".container-layer");
			if (ptrParent !== false) {
				// Why yes, the click was within a layer.  But which one?
				var strLabel = ptrParent.querySelector(".label-layer .collapsible-label").innerText,
					myIndex = this.getLayerIndexByName(strLabel);
				this.selectLayer(myIndex);
			}
		}
	},
	
	handleBlur: {
		value: function(event) {
			var ptrParent = nj.queryParentSelector(event.target, ".tl_leftpane");
			if (ptrParent !== false) {
				// We were clicking somewhere within the left pane, so we shouldn't blur.
			} else {
				this.selectLayer("none");
			}
		}
	},

     handleNewLayer:{
        value:function(event){
            // Add a new layer.  It should be added above the currently selected layer,
            // Or at the end, if no layer is selected.
             var hashIndex =0 ,hashVariable=0,layerResult,trackResult,layerObject,trackObject,dLayer,parentNode;

             if(this._hashFind){
                while(layerResult = this.returnedObject[hashIndex]){
                    trackResult=this.returnedTrack[hashIndex];
                    if(layerResult.deleted!==true){
                        this.arrLayers.push(layerResult);
                        this.arrTracks.push(trackResult);
                    }
                    hashIndex++;
                }
             this._hashFind=false;
             return;
             }


//                if(this.addButtonClicked){
//                    layerObject = this.hashInstance.getItem(this.application.ninja.currentSelectedContainer.uuid);
//                    trackObject = this.hashTrackInstance.getItem(this.application.ninja.currentSelectedContainer.uuid);
//                    if(layerObject!==undefined){
//                            while(layerObject[hashVariable]){
//                                if(event.detail.parentElement!==this.application.ninja.currentSelectedContainer){
//                                    dLayer=this.hashInstance.getItem(event.detail.parentNode.uuid);
//                                        while(dLayer[hashVariable]){
//                                            if(dLayer[hashVariable].element===event.detail){
//                                                dLayer[hashVariable].deleted=true;
//                                                parentNode=dLayer[hashVariable].parentElement;
//                                                break;
//                                            }
//                                            hashVariable++;
//                                        }
//                                        this._setBreadCrumb=true;
//                                        NJevent('breadCrumbTrail',{"element":parentNode,"setFlag":this._setBreadCrumb});
//
//                                }
//                                else if(layerObject[hashVariable].element===event.detail){
//                                    this.arrLayers.splice(layerObject[hashVariable].layerPosition,0,layerObject[hashVariable]);
//                                    this.arrTracks.splice(trackObject[hashVariable].trackPosition,0,trackObject[hashVariable]);
//                                    this._isLayerAdded=true;
//                                    break;
//                                }
//                                hashVariable++;
//                                this._isLayerAdded=false;
//                            }
//                    }
//                }


                      var newLayerName = "",
                        //thingToPush = Layer.create(),
                        thingToPush = {},
                        // newTrack = TimelineTrack.create(),
                        newTrack = {},
                        myIndex = 0;

                    // Build the thingToPush object
                        if(_firstLayerDraw){
                            if(this.application.ninja.currentSelectedContainer.id==="UserContent"){
                                this._hashKey="123";
                            }
                        }

                        this.currentLayerNumber = this.currentLayerNumber +1;
                        newLayerName = "Layer " + this.currentLayerNumber;
                        thingToPush.layerName = newLayerName;
                        thingToPush.layerID = this.currentLayerNumber;
                        thingToPush.isMainCollapsed = true;
                        thingToPush.isPositionCollapsed = true;
                        thingToPush.isTransformCollapsed = true;
                        thingToPush.isStyleCollapsed = false;
                        thingToPush.arrLayerStyles = [];
                        thingToPush.element=[];
                        thingToPush.deleted=false;
                        thingToPush.isSelected = false;
                        thingToPush.parentElement=this.application.ninja.currentSelectedContainer;
                       // this.layerElement.dataset.parentUUID=this.application.ninja.currentSelectedContainer.uuid;

                        newTrack.trackID = this.currentLayerNumber;
                        newTrack.isMainCollapsed = true;
                        newTrack.isPositionCollapsed = true;
                        newTrack.isTransformCollapsed = true;
                        newTrack.isStyleCollapsed = false;
                        newTrack.tweens = [];

                        // If a layer is selcted, splice the new layer on top
                        // Otherwise, just push the new layer in at the bottom.

                        if (!!this.layerRepetition.selectedIndexes) {
                            myIndex = this.layerRepetition.selectedIndexes[0];
                            this.hashInstance.setItem(this._hashKey,thingToPush,myIndex);
                            this.hashTrackInstance.setItem(this._hashKey,newTrack,myIndex);
                            thingToPush.layerPosition=myIndex;
                            thingToPush.isSelected = true;
                            newTrack.trackPosition=myIndex;
                            this.arrLayers.splice(myIndex, 0, thingToPush);
                            this.arrTracks.splice(myIndex, 0, newTrack);
                            /*
                            this.currentLayerSelected= this.arrLayers[myIndex];
                            var i = 0,
								arrLayersLength = this.arrLayers.length;
							for (i = 0; i < arrLayersLength; i++) {
								if (i === myIndex) {
									this.arrLayers[i].isSelected = true;
								} else {
									this.arrLayers[i].isSelected = false;
								}
							}
                            this.layerRepetition.selectedIndexes = [myIndex];
                            */
                           
                           this.selectLayer(myIndex);
                           
                        } else {
                            this.arrLayers.splice(0, 0, thingToPush);
                            this.arrTracks.splice(0, 0, newTrack);
                            thingToPush.layerPosition=this.arrLayers.length-1;
                            newTrack.trackPosition=this.arrTracks.length-1;
                            this.currentLayerSelected= this.arrLayers[this.arrLayers.length-1];

                            this.hashInstance.setItem(this._hashKey,thingToPush,thingToPush.layerPosition);
                            this.hashTrackInstance.setItem(this._hashKey,newTrack,newTrack.trackPosition);

                          }




        }
     },

     handleDeleteLayer:{
        value:function(event){
             var dLayer,dTrack,parentNode,hashVariable=0,k=0,index=0,j=0;

                if (this.arrLayers.length > 0) {
                     if(this._undoElementDeleted){
                        if(event.detail.dataset.parentUUID!==this.application.ninja.currentSelectedContainer.uuid){
                            dLayer=this.hashInstance.getItem(event.detail.dataset.parentUUID);
                            while(dLayer[hashVariable]){
                                if(dLayer[hashVariable].element===event.detail){
                                    dLayer[hashVariable].deleted=true;
                                    parentNode=dLayer[hashVariable].parentElement;
                                    break;
                                }
                                hashVariable++;
                            }
                            this._setBreadCrumb=true;
                            NJevent('breadCrumbTrail',{"element":parentNode,"setFlag":this._setBreadCrumb});
                        }else{
                            dLayer=this.hashInstance.getItem(event.detail.dataset.parentUUID)
                            while(dLayer[hashVariable]){
                                  if(dLayer[hashVariable].deleted===true){

                                  }else if(dLayer[hashVariable].element.uuid === event.detail.uuid){
                                            while(this.arrLayers.length){
                                               if(dLayer[hashVariable].layerID===this.arrLayers[k].layerID){
                                                     dLayer[hashVariable].deleted=true;
                                                     this.arrLayers.splice(k,1);
                                                     this.arrTracks.splice(k,1);
                                                     break;
                                               }
                                               k++;
                                            }
                                        }
                                  hashVariable++;
                            }
                        }
                     }
                    else{
                            if (!!this.layerRepetition.selectedIndexes) {
                                    var myIndex = this.layerRepetition.selectedIndexes[0];
                                    dLayer = this.hashInstance.getItem(this._hashKey);
                                    dTrack = this.hashTrackInstance.getItem(this._hashKey);
                                    dLayer[myIndex].deleted=true;

                                    this.arrLayers.splice(myIndex, 1);
                                    this.arrTracks.splice(myIndex, 1);

                        }   else if(this._deleteKeyDown) {
                                  dLayer = this.hashInstance.getItem(this._hashKey);
                                  dTrack = this.hashTrackInstance.getItem(this._hashKey);

                                      if(this.deleteElement === this.application.ninja.currentSelectedContainer){
                                          while(dLayer[hashVariable]){
                                                dLayer[hashVariable].deleted=true;
                                                hashVariable++;
                                          }

                                          this.dObject=this.hashInstance.getItem(this.removeLayerFromParentUUid);
                                          hashVariable=0;
                                          while(this.dObject[hashVariable]){
                                             if(this.application.ninja.currentSelectedContainer===this.dObject[hashVariable].element){
                                                      this.dObject[hashVariable].deleted=true;
                                                      this._setBreadCrumb=true;
                                                      NJevent('breadCrumbTrail',{"element":this.currentParentNode,"setFlag":this._setBreadCrumb});
                                                      this._setBreadCrumb=false;
                                                      break;
                                             }
                                             hashVariable++;
                                          }
                                          this._deleteKeyDown=false;
                                  } else if(this.deleteElement!== this.application.ninja.currentSelectedContainer){

                                          while(dLayer[hashVariable]){
                                              if(dLayer[hashVariable].deleted===true){

                                              }else if(dLayer[hashVariable].element.uuid === this.deleteElement.uuid){
                                                   while(this.arrLayers.length){
                                                       if(dLayer[hashVariable].layerID===this.arrLayers[k].layerID){
                                                             dLayer[hashVariable].deleted=true;
                                                             this.arrLayers.splice(k,1);
                                                             this.arrTracks.splice(k,1);
                                                             break;
                                                       }
                                                       k++;
                                                   }
                                              }
                                              hashVariable++;
                                         }
                                  }
                            }
                              else{
                                        dLayer = this.hashInstance.getItem(this._hashKey);
                                        dTrack = this.hashTrackInstance.getItem(this._hashKey);
                                        dLayer[this.arrLayers.length-1].deleted=true;
                                        this.arrLayers.pop();
                                        this.arrTracks.pop();
                                  }
                    }

               }else  if (this.arrLayers.length <=  0) {
                            if(this._undoElementDeleted){
                                if(event.detail.dataset.parentUUID!==this.application.ninja.currentSelectedContainer.uuid){
                                        dLayer=this.hashInstance.getItem(event.detail.dataset.parentUUID);
                                        while(dLayer[hashVariable]){
                                            if(dLayer[hashVariable].element===event.detail){
                                                dLayer[hashVariable].deleted=true;
                                                parentNode=dLayer[hashVariable].parentElement;
                                                break;
                                            }
                                            hashVariable++;
                                        }
                                        this._setBreadCrumb=true;
                                        NJevent('breadCrumbTrail',{"element":parentNode,"setFlag":this._setBreadCrumb});
                                }
                            }else
                                if(this._deleteKeyDown) {
                                          this.dObject=this.hashInstance.getItem(this.removeLayerFromParentUUid);
                                          hashVariable=0;
                                          while(this.dObject[hashVariable]){
                                             if(this.application.ninja.currentSelectedContainer===this.dObject[hashVariable].element){
                                                      this.dObject[hashVariable].deleted=true;
                                                      this._setBreadCrumb=true;
                                                      NJevent('breadCrumbTrail',{"element":this.currentParentNode,"setFlag":this._setBreadCrumb});
                                                      this._setBreadCrumb=false;
                                                      break;
                                             }
                                             hashVariable++;
                                          }
                                }
                }
                // TODO: actually remove the selected style from the layer. (Maybe by publishing an event?)

        }
    },

    handleElementAdded: {
        value: function(event) {
           this.layerElement=event.detail;
           this._isElementAdded=true;
           this.currentLayerSelected.element.push(event.detail);
           this._isElementAdded=false;
        }
    },



//    handleDeleteSelection:{
//        value:function(event){
//            var length;
//            this._deleteKeyDown=true;
//            this.deleteElement = event.detail[0];
//            length =this.currentLayerSelected.element.length-1;
//            while(length >= 0){
//                if(this.currentLayerSelected.element[length]===this.deleteElement){
//                    this.currentLayerSelected.element.splice(length,0);
//                }
//            }
//
//        }
//    },

    handleElementDeleted: {
        value: function(event) {
            var length;
             this._deleteKeyDown=true;
             this.deleteElement = event.detail;
             length =this.currentLayerSelected.element.length-1;
             while(length >= 0){
                if(this.currentLayerSelected.element[length]===this.deleteElement){
                    this.currentLayerSelected.element.splice(length,1);
                    break;
                }
             length--;
            }
        }
    },
    drawTimeMarkers:{
        value:function(){
            var i;
            var totalMarkers = Math.floor(this.time_markers.offsetWidth / 80);
            for(i=0;i<totalMarkers;i++){
                var timeMark = document.createElement("div");
                var markValue = this.calculateTimeMarkerValue(i);
                timeMark.className = "timemark";
                timeMark.innerHTML = markValue;
                this.time_markers.appendChild(timeMark);
            }
        }
    },

    calculateTimeMarkerValue:{
        value:function(currentMarker){
            var timeToReturn;
            var currentMilliseconds = currentMarker * this.millisecondsOffset;

            var sec = (Math.floor((currentMilliseconds/1000)))%60;
            var min = (Math.floor((currentMilliseconds/1000)/60))%60;

            var milliSec = String(Math.round(currentMilliseconds/10));
            var returnMillisec = milliSec.slice(milliSec.length-2, milliSec.length);

            var returnSec;
            var returnMin;
            if(sec < 10){
                returnSec = "0" + sec;
            } else {
                returnSec = sec;
            }
            if(min < 10){
                returnMin = "0" + min;
            } else {
                returnMin = min;
            }
            if(currentMarker == 0) {
                returnMillisec = "00";
            }

            timeToReturn = returnMin + ":" + returnSec + ":" + returnMillisec;

            return timeToReturn;
        }
    },

    createLayerHashTable: {
        value : function(key,value){
            var hashLayerObject;

                   hashLayerObject = Object.create(Object.prototype, {
                        counter:{
                                  value:0,
                                  writable:true
                                },

                       setItem: {
                           value: function(key,value,index) {
//                               console.log(this.application.ninja.currentSelectedContainer)
                                   if(hashLayerObject[key]===undefined){
                                       hashLayerObject[key]={};
                                   }
                                   if(hashLayerObject[key][index]!== undefined){

                                        this.counter=index;
                                        while(hashLayerObject[key][this.counter]){
                                            this.counter++;
                                        }

                                        while(this.counter!==index){
                                            hashLayerObject[key][this.counter]=hashLayerObject[key][this.counter-1];
                                            this.counter=this.counter-1;
                                        }
                                   }
                                   hashLayerObject[key][index] = value;
                                   this.counter=0;
                           }
                       },

                       getItem: {
                           value: function(key) {
                               return hashLayerObject[key];
                           }
                       }
                   });

                   return hashLayerObject;

        }
    },

    createTrackHashTable: {
        value : function(key,value){
                var hashTrackObject;

                       hashTrackObject = Object.create(Object.prototype, {
                            counter:{
                                      value:0,
                                      writable:true
                                    },

                           setItem: {
                               value: function(key,value,index) {
                                       if(hashTrackObject[key]===undefined){
                                           hashTrackObject[key]={};
                                       }

                                       if(hashTrackObject[key][index]!== undefined){

                                           this.counter=index;
                                           while(hashTrackObject[key][this.counter]){
                                                 this.counter++;
                                           }

                                           while(this.counter!==index){
                                                hashTrackObject[key][this.counter]=hashTrackObject[key][this.counter-1];
                                                this.counter=this.counter-1;
                                           }
                                       }
                                       hashTrackObject[key][index] = value;
                                       this.counter=0;
//                                       console.log(hashTrackObject)
                               }
                           },

                           getItem: {
                               value: function(key) {
                                   return hashTrackObject[key];
                               }
                           }
                       });

                       return hashTrackObject;

        }
    },
    
    selectLayer : {
    	value: function(layerIndex) {
    		// Select a layer based on its index.
    		// use layerIndex = "none" to deselect all layers.
    		var i = 0,
    			arrLayersLength = this.arrLayers.length;
    			
    		// First, update this.arrLayers[].isSelected
    		for (i = 0; i < arrLayersLength; i++) {
    			if (i === layerIndex) {
    				this.arrLayers[i].isSelected = true;
    			} else {
    				this.arrLayers[i].isSelected = false;
    			}
    		}
    		
    		// Next, update this.layerRepetition.selectedIndexes and this.currentLayerSelected.
    		if (layerIndex !== "none") {
    			this.layerRepetition.selectedIndexes = [layerIndex];
    			this.currentLayerSelected = this.arrLayers[layerIndex]
    		} else {
    			this.layerRepetition.selectedIndexes = null;
    			this.currentLayerSelected = null;
    		}
    	}
    },
    
    getLayerIndexByID : {
    	value: function(layerID) {
    		// Get the index in this.arrLayers that matches a particular layerID.
    		// Returns false if no match.
    		var i = 0, 
    			returnVal = false,
    			arrLayersLength = this.arrLayers.length;
    			
    		for (i=0; i < arrLayersLength; i++) {
    			if (this.arrLayers[i].layerID === layerID) {
    				returnVal = i;
    			}
    		}
    		
    		return returnVal;
    		
    	}
    },
    getLayerIndexByName : {
    	value: function(layerName) {
    		// Get the index in this.arrLayers that matches a particular layerName
    		// Returns false if no match
    		var i = 0, 
    			returnVal = false,
    			arrLayersLength = this.arrLayers.length;
    			
    		for (i=0; i < arrLayersLength; i++) {
    			if (this.arrLayers[i].layerName === layerName) {
    				returnVal = i;
    			}
    		}
    		
    		return returnVal;
    	}
    }

    /* === END: Controllers === */

});