/* <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").Montage;
    
var FlowOffset = exports.FlowOffset = Montage.create(Montage, {
	
	hasTemplate: {
	    value: false
	},

    isAnimating: {
        enumerable: false,
        value: false
    },
    
	component: {
	    value: null
	},
	
	draw: {
	    value: function () {
	        if (this.isAnimating) {
	            this._interval();
	        }
	    }
	},
	
	deserializedFromTemplate: {
	    value: function () {
	        var oldComponentDraw = this.component.draw,
                self = this;
            
            this.component.draw = function () {
                self.draw();
                oldComponentDraw.call(self.component);
            };
	    }
	},
	
	_hasElasticScrolling: {
	    enumerable: false,
	    value: true
	},
	
	hasElasticScrolling: {
	    get: function () {
	        return this._hasElasticScrolling;
	    },
	    set: function (value) {
	        this._hasElasticScrolling=(value===true)?true:false;
	    }
	},

	_selectedSlideIndex: {
	    enumerable: false,
	    value: null
	},
	
	selectedSlideIndex: {
	    get: function () {
	        return this._selectedSlideIndex;
	    },
	    set: function (value) {
	        this._selectedSlideIndex=value;
	        if (typeof this.animatingHash[this._selectedSlideIndex] !== "undefined") {
	            var tmp=this.slide[this._selectedSlideIndex].x;
	            this.origin+=(this._selectedSlideIndex*this._scale)-tmp;
            }
	    }
	},
	
	_selectedComponent: {
	    enumerable: false,
	    value: null
	},
	
	selectedComponent: {
	    get: function () {
	        return this._selectedComponent;
	    },
	    set: function (value) {	    
	        this._selectedComponent=value;
	        this.selectedSlideIndex=value;
	    }
	},
	
    _animating: {
        enumerable: false,
        value: null
    },
    
    animating: {
        enumerable: false,
        get: function () {
            if (!this._animating) {
                this._animating=[];
            }
            return this._animating;
        },
        set: function () {
        }
    },
    
    _animatingHash: {
        enumerable: false,
        value: null
    },
    
    animatingHash: {
        enumerable: false,
        get: function () {
            if (!this._animatingHash) {
                this._animatingHash={};
            }
            return this._animatingHash;
        },
        set: function () {
        }
    },
    
    _slide: {
        enumerable: false,
        value: null
    },
    
    slide: {
        enumerable: false,
        get: function () {
            if (!this._slide) {
                this._slide={};
            }
            return this._slide;
        },
        set: function () {
        }
    },    
    
    startAnimating: {
        enumerable: false,
        value: function (index, pos) {
            if (typeof this.animatingHash[index] === "undefined") {
                var length=this.animating.length;
                
                this.animating[length]=index;
                this.animatingHash[index]=length;
                this.slide[index]={
                    speed: 0,
                    x: pos
                };
            } else {
                this.slide[index].x=pos;
            }
        }
    },

    stopAnimating: {
        enumerable: false,    
        value: function (index) {
            if (typeof this.animatingHash[index] !== "undefined") {
                this.animating[this.animatingHash[index]]=this.animating[this.animating.length-1];
                this.animatingHash[this.animating[this.animating.length-1]]=this.animatingHash[index];
                this.animating.pop();
                delete this.animatingHash[index];
                delete this.slide[index];
            }
        }
    },
    
    _range: {
        value: 15
    },
    
    lastDrawTime: {
        value: null
    },
    
	_origin: {
		enumerable: false,
        value: 0
    },
	
	origin: {
	    get: function () {
	        return this._origin;
	    },
	    set: function (value) {
	        if (this._hasElasticScrolling) {
	        	var i,
                    n,
                    min=this._selectedSlideIndex-this._range,
                    max=this._selectedSlideIndex+this._range+1,
                    tmp,                    
                    j,
                    x,
                    self=this;
                
                tmp=value-this._origin;
                if (min<0) {
                    min=0;
                }          

                if (!this.isAnimating) {
                    this.lastDrawTime=Date.now();
                }
                for (i=min; i<max; i++) {
                    if (i!=this._selectedSlideIndex) {
                        if (typeof this.animatingHash[i] === "undefined") {
                            x=i*this._scale;
                        } else {            
                            x=this.slide[i].x;
                        }
                        x+=tmp;
                        if (i<this._selectedSlideIndex) {
                            if (x<i*this._scale) {
                                this.startAnimating(i, x);
                            }
                        } else {
                            if (x>i*this._scale) {
                                this.startAnimating(i, x);
                            }
                        }
                    }
                }
                this.stopAnimating(this._selectedSlideIndex);
                                
                if (!this.isAnimating) {
                    this._interval=function () {
                        var animatingLength=self.animating.length,
                            n, j, i, _iterations=8,
                            time=Date.now(),
                            interval1=self.lastDrawTime?(time-self.lastDrawTime)*0.015:0,
                            interval=interval1/_iterations,
                            mW=self._scale, x,
                            epsilon=.5;
                                                        
                        for (n=0; n<_iterations; n++) {
                            for (j=0; j<animatingLength; j++) {
                                i=self.animating[j];
                                if (i<self._selectedSlideIndex) {
                                    if (typeof self.animatingHash[i+1] === "undefined") {
                                        x=((i+1)*self._scale);
                                    } else {            
                                        x=self.slide[i+1].x;
                                    }
                                    self.slide[i].speed=x-self.slide[i].x-mW;
                                } else {
                                    if (typeof self.animatingHash[i-1] === "undefined") {
                                        x=((i-1)*self._scale);
                                    } else {            
                                        x=self.slide[i-1].x;
                                    }
                                    self.slide[i].speed=x-self.slide[i].x+mW;	
                                }
                                self.slide[i].x+=(self.slide[i].speed)*interval;
                            }
                        }
               			j=0;
                        while (j<animatingLength) {
                            i=self.animating[j];
                            if (i<self._selectedSlideIndex) {
                                if (self.slide[i].x>i*self._scale-epsilon) {
                                    self.stopAnimating(i);
                                    animatingLength--;
                                } else {
                                    j++;
                                }
                            } else {
                                if (self.slide[i].x<i*self._scale+epsilon) {
                                    self.stopAnimating(i);
                                    animatingLength--;						
                                } else {
                                    j++;
                                }
                            }
                        }
                        self.lastDrawTime=time;
                        if (!animatingLength) {
                            self.isAnimating=false;
                        } else {
                            if (!self.isAnimating) {
                                self.isAnimating=true;
                            }
                        }

                        self.component.needsDraw=true;
                    }    
                }
                if (!this.isAnimating) {
                    this._interval();
                }
	        }
	        this._origin=value;
	        if (!this.animating.length) {
    	        self.component.needsDraw=true;
    	    }
	    }
	},
	
	_scale: {
	    enumerable: false,
	    value: 100
	},
	
    scale: {
        get: function () {
	        return this._scale;
	    },
	    set: function (value) {
	        //var oldScale = this._scale;
	        
	        this._scale = value;
	        this.length = value * (this._numberOfNodes-1);
	        this.offset=true;
	    }
    },
    
    _numberOfNodes: {
        enumerable: false,
        value: 0
    },
    
    numberOfNodes: {
        get: function () {
            return this._numberOfNodes;
        },
        set: function (value) {
            this._numberOfNodes = value;
            this.length = (value-1) * this._scale;
            this.component.needsDraw=true;
        }
    },
    
    _length: {
        enumerable: false,
        value: 0
    },
    
    length: {
        get: function () {
            return this._length;
        },
        set: function (value) {
            if (value<0) {
                this._length = 0;
            } else {
                this._length = value;
            }
        }
    },
    
    _offset: {
        enumerable: false,
        value: {
            value: function (nodeNumber) {
                return 0;
            }
        }
    },
    
    offset: {
        get: function () {
            return this._offset;
        },
        set: function () {
            var self = this;
            
            this._offset = {
                value: function (nodeNumber) {
                    if (typeof self.animatingHash[nodeNumber] === "undefined") {
                        return {
                            time: (nodeNumber*self._scale)-self._origin,
                            speed: 0
                        }
                    } else {                        
                        return {
                            time: self.slide[nodeNumber].x-self.origin,
                            speed: self.slide[nodeNumber].speed
                        }
                    }
                }
            };
        }
    }
    
});