var OuterScroller = new Class({

   options: {
       area: 20,
       addarea: 0,
       outArea: {
           type : 'V' ,
           width : null,
           height : null
       },
       velocity: 1,
       onChange: function(x, y){
           this.element.scrollTo(x, y);
       },
       allways: 0,
       runVelocity: null
          },

   initialize: function(element, options){
       this.setOptions(options);
       this.element = $(element);
       this.mousemover = ([window, document].contains(element)) ? $(document.body) : this.element;
       if (this.options.outArea.type=='H'){
           this.cel = this.element.getElements( 'div' );
           this.child=$(this.cel[0].id);
           this.childs = this.child.getElements('div');
           var totwidth =0;
           for(i=0;i<=(this.childs.length-1);i++){
               var child1 = this.childs[i];
               totwidth+=child1.getSize().size.x;
           }
           this.child.setAttribute('width',totwidth);
       }
       if (this.options.addarea==1){
           this.addOutArea(this);
       }
       if (this.options.allways==1){
           if (this.options.runVelocity==null)
               this.options.runVelocity=this.options.velocity;
           this.createLoop();
           this.start4();
       }
   },
            start: function(){
       this.coord = this.getCoords.bindWithEvent(this);
       this.mousemover.addListener('mousemove', this.coord);
   },

   start2: function(){
       this.startUp = this.initStart2.bindWithEvent(this);
       this.dmu.addListener('mousemove', this.startUp);
   },
   initStart2: function(){
       if (this.timer) this.timer = $clear(this.timer);
       if (this.timer3) this.timer3 = $clear(this.timer3);
       if (this.timer4) this.timer4 = $clear(this.timer4);
       if (!this.timer2) this.timer2 = this.scrollUp.periodical(50, this);
   },
      start3: function(){
       this.startDown = this.initStart3.bindWithEvent(this);
       this.dmd.addListener('mousemove', this.startDown);
   },
   initStart3: function(){
       if (this.timer) this.timer = $clear(this.timer);
       if (this.timer2) this.timer2 = $clear(this.timer2);
       if (this.timer4) this.timer4 = $clear(this.timer4);
       if (!this.timer3) this.timer3 = this.scrollDown.periodical(50, this);
   },

   start4: function(){
       if (this.timer) this.timer = $clear(this.timer);
       if (this.timer2) this.timer2 = $clear(this.timer2);
       if (this.timer3) this.timer3 = $clear(this.timer3);
       if (!this.timer4) this.timer4 = this.runScroll.periodical(50, this);
   },

   stop: function(){
       this.mousemover.removeListener('mousemove', this.coord);
       this.timer = $clear(this.timer);
           this.start4();
   },
   stop2: function(){
       this.timer2 = $clear(this.timer2);
           this.start4();
   },
   stop3: function(){
       this.timer3 = $clear(this.timer3);
       this.start4();
   },
   getCoords: function(event){
       this.page = (this.element == window) ? event.client : event.page;
       if (this.timer2) this.timer2 = $clear(this.timer2);
       if (this.timer3) this.timer3 = $clear(this.timer3);
       if (this.timer4) this.timer4 = $clear(this.timer4);
       if (!this.timer) this.timer = this.scroll.periodical(50, this);
   },
      checkBefore: function(direction){
       var el = this.element.getSize();
       var Ymax = this.element.getSize().scrollSize.y-this.element.getSize().size.y;
       var Xmax = this.element.getSize().scrollSize.x-this.element.getSize().size.x;
           if (this.options.outArea.type=='H'){
               if (el.scroll.x==0){
                   var scrollto = this.elementContenor.childNodes[0].getSize().size.x;
                   this.element.scrollTo(scrollto,0);
                   this.elementChild1=this.elementChildCC.clone();
                  this.elementContenor.setStyle('width',(this.elementContenor.childNodes[0].getSize().size.x)*2+'px');
                   if (this.elementContenor.childNodes.length>1)
                       if (this.elementContenor.childNodes[1] )
                           this.elementContenor.childNodes[1].remove();
                  this.elementChild1.injectBefore(this.elementContenor.childNodes[0]);
               }
               if (el.scroll.x==Xmax){
                   var scrollto = this.element.getSize().scroll.x-this.elementContenor.childNodes[0].getSize().size.x;
                   this.element.scrollTo(scrollto,0);
                  this.elementContenor.setStyle('width',(this.elementContenor.childNodes[0].getSize().size.x)*2+'px');
                   if (this.elementContenor.childNodes.length>1)
                       if (this.elementContenor.childNodes[0] )
                           this.elementContenor.childNodes[0].remove();
                   this.elementChild1=this.elementChildCC.clone();
                  this.elementChild1.injectAfter(this.elementContenor.childNodes[0]);
               }
           }else{
               if (el.scroll.y==0){
                   var scrollto = this.elementContenor.childNodes[0].getSize().size.y;
                   this.element.scrollTo(0,scrollto);
                   this.elementChild1=this.elementChildCC.clone();
                   if (this.elementContenor.childNodes.length>1)
                       if (this.elementContenor.childNodes[1] )
                           this.elementContenor.childNodes[1].remove();
                  this.elementChild1.injectBefore(this.elementContenor.childNodes[0]);
               }
               if (el.scroll.y==Ymax){
                   var scrollto = this.element.getSize().scroll.y-this.elementContenor.childNodes[0].getSize().size.y;
                   this.element.scrollTo(0,scrollto);
                   if (this.elementContenor.childNodes.length>1)
                       if (this.elementContenor.childNodes[0] )
                           this.elementContenor.childNodes[0].remove();
                   this.elementChild1=this.elementChildCC.clone();
                  this.elementChild1.injectAfter(this.elementContenor.childNodes[0]);
               }
           }
   },
      createLoop: function(){
           this.cel = this.element.getElements( 'div' );
           this.elementContenor=$(this.cel[0].id);
           this.spacer = new Element('div');
           this.spacer.setStyle('clear','both');
           this.element.appendChild(this.spacer);
           this.elementChild = this.elementContenor.clone();
           this.elementChild.setStyle('float','left');
           this.elementChildCC = this.elementChild.clone();
           this.elementContenor.empty();
           this.elementContenor.appendChild(this.elementChild);
   },
      runScroll: function(){
       if (this.options.allways==1)
           this.checkBefore('down');
       var el = this.element.getSize();
       var Ymax = this.element.getSize().scrollSize.y-parseInt(this.element.getStyle('height'));
       var Xmax = this.element.getSize().scrollSize.x-parseInt(this.element.getStyle('width'));
       if (this.options.outArea.type=='H'){
           if (el.scroll.x<Xmax){
               el.scroll.x+=this.options.velocity*this.options.runVelocity;
               if (el.scroll.x<Xmax)
                   this.element.scrollTo(el.scroll.x,0);
               else
                   this.element.scrollTo(Xmax,0);
           }
       }else{
           if (el.scroll.y<Ymax){
               el.scroll.y+=this.options.velocity*this.options.runVelocity;
               if (el.scroll.y<Ymax)
                   this.element.scrollTo(0,el.scroll.y);
               else
                   this.element.scrollTo(0,Ymax);
           }
       }
   },
            scrollUp: function(){
       if (this.options.allways==1)
           this.checkBefore('up');
       var el = this.element.getSize();
       var Ymax = this.element.getSize().scrollSize.y-parseInt(this.element.getStyle('height'));
       var Xmax = this.element.getSize().scrollSize.x-parseInt(this.element.getStyle('width'));
       if (this.options.outAreaType=='H'){
           if (el.scroll.x<Xmax){
               el.scroll.x-=this.options.velocity*this.options.area;
               if (el.scroll.x<Xmax)
                   this.element.scrollTo(el.scroll.x,0);
               else
                   this.element.scrollTo(0,0);
           }
       }else{
           if (el.scroll.y>0){
               el.scroll.y-=this.options.velocity*this.options.area;
               if (el.scroll.y>0)
                   this.element.scrollTo(0,el.scroll.y);
               else
                   this.element.scrollTo(0,0);
           }
       }
   },
      scrollDown: function(){
       if (this.options.allways==1)
           this.checkBefore('down');
       var el = this.element.getSize();
       var Ymax = this.element.getSize().scrollSize.y-parseInt(this.element.getStyle('height'));
       var Xmax = this.element.getSize().scrollSize.x-parseInt(this.element.getStyle('width'));
       if (this.options.outArea.type=='H'){
           if (el.scroll.x<Xmax){
               el.scroll.x+=this.options.velocity*this.options.area;
               if (el.scroll.x<Xmax)
                   this.element.scrollTo(el.scroll.x,0);
               else
                   this.element.scrollTo(Xmax,0);
           }
       }else{
           if (el.scroll.y<Ymax){
               el.scroll.y+=this.options.velocity*this.options.area;
               if (el.scroll.y<Ymax)
                   this.element.scrollTo(0,el.scroll.y);
               else
                   this.element.scrollTo(0,Ymax);
           }
       }
          },
      scroll: function(){
       if (this.options.allways==1)
           this.checkBefore();
       var el = this.element.getSize();
       var pos = this.element.getPosition();

       var change = {'x': 0, 'y': 0};
       for (var z in this.page){
           if (this.page[z] < (this.options.area + pos[z]) && el.scroll[z] != 0)
               change[z] = (this.page[z] - this.options.area - pos[z]) * this.options.velocity;
           else if (this.page[z] + this.options.area > (el.size[z] + pos[z]) && el.scroll[z] + el.size[z] != el.scrollSize[z])
               change[z] = (this.page[z] - el.size[z] + this.options.area - pos[z]) * this.options.velocity;
       }
       if (change.y || change.x) this.fireEvent('onChange', [el.scroll.x + change.x, el.scroll.y + change.y]);
   },
      addOutArea: function(){
       var parentElement = this.element.getParent();
       //alert('pe '+parentElement.id);
       switch (this.options.outArea.type){
           case 'H':
               if (this.options.outArea.width==null)
                   this.options.outArea.width=20;
               if (this.options.outArea.height==null)
                   this.options.outArea.height=this.element.offsetHeight;
               break;
           case 'V':
           default :
               if (this.options.outArea.width==null)
                   this.options.outArea.width=this.element.offsetWidth;
               if (this.options.outArea.height==null)
                   this.options.outArea.height=20;
               break;
       }
       this.options.outArea.width=parseInt(this.options.outArea.width);
       this.options.outArea.height=parseInt(this.options.outArea.height);
       if (!($('upmouse'))){
           this.dmu = new Element('div',{
               'id':'upmouse',
               'styles':{
                   'position': 'absolute',
                   'width': this.options.outArea.width+'px',
                   'height':  this.options.outArea.height+'px'
               },
               'events':{
                   'mouseenter':this.start2.bindWithEvent(this),
                   'mouseleave':this.stop2.bindWithEvent(this)
               }
           });
           if (this.options.outArea.type=='H') {
                this.dmu.setStyles({
                    'top' : this.element.getTop()+'px',
                    'left' : this.element.getLeft()-this.options.outArea.width+'px'
                });
           } else {
                this.dmu.setStyles({
                    'margin-top' : '-'+this.options.outArea.height+'px'
                });
           }
           this.dmu.injectBefore(this.element.id);
       }else{
           this.dmd = $('upmouse');
           this.dmd.addEvents({
               'mouseenter':this.start3.bindWithEvent(this),
               'mouseleave':this.stop3.bindWithEvent(this)
           });
       }
       if (!($('downmouse'))){
           this.dmd = new Element('div',{
               'id':'downmouse',
               'styles':{
                   'position': 'absolute',
                   'width': this.options.outArea.width+'px',
                   'height':  this.options.outArea.height+'px'
               },
               'events':{
                   'mouseenter':this.start3.bindWithEvent(this),
                   'mouseleave':this.stop3.bindWithEvent(this)
               }
           });
           if (this.options.outArea.type=='H') {
                this.dmd.setStyles({
                    'top' : this.element.getTop()+'px',
                    'left' : this.element.getLeft()+this.element.getSize().size.x+'px'
                });
           }
           this.dmd.injectAfter(this.element.id);
       }else{
           this.dmd = $('downmouse');
           this.dmd.addEvents({
               'mouseenter':this.start3.bindWithEvent(this),
               'mouseleave':this.stop3.bindWithEvent(this)
           });
       }
   }
});
OuterScroller.implement(new Events, new Options);
