//    RTRails - Realtime on Rails
//    Copyright 2006 Martin Scheffler, Markus Hartleb
//    email: wooyay@web.de
//
//
//    This file is part of RTRails.
//
//    RTRails is free software; you can redistribute it and/or modify
//    it under the terms of the GNU Lesser General Public License as published by
//    the Free Software Foundation; either version 2.1 of the License, or
//    (at your option) any later version.
//
//    RTRails is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU Lesser General Public License for more details.
//
//    You should have received a copy of the GNU Lesser General Public License
//    along with RTRails; if not, write to the Free Software
//    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA


Window = Class.create();
Window.prototype = {
    initialize:function() {
      
      var options = Object.extend({
        id:-1,
        name:"noname",
        min_width:100,
        min_height:100,
        screen_safety_border:20,
        width:100,
        height:100,
        posx:100,
        posy:100,
        z_index:-1,
        is_hidden:true,
        is_minimized:false
      }, arguments[0] || {});
      this.options = options;
    
      this.start();
      
    },
    start: function() {
    
    this.closing=false;
    this.event("startinit");
    this.element = $(this.options.id+""); 
 
    this.draghandle = $(this.options.id + "_drag_handle");
    this.resizehandle = $(this.options.id + "_resize_handle");
    this.fader = $(this.options.id + "_middleslice");

    this.tab1 = $(this.options.id + "_tab1");
    this.tab2 = $(this.options.id + "_tab2");

    this.buttab1 = $(this.options.id + "_buttab1");
    this.buttab2 = $(this.options.id + "_buttab2");
    
    this.topslice = $(this.options.id + "_topslice");
    Element.cleanWhitespace(this.topslice);
    this.middleslice = $(this.options.id + "_middleslice");
    Element.cleanWhitespace(this.middleslice);
    this.bottomslice = $(this.options.id + "_bottomslice");
    Element.cleanWhitespace(this.bottomslice);
    
    
   
    
    /*------------ setup the window DIVs -------------*/
    //set contents and border divs to window height
    this.border_l = this.middleslice.childNodes[0];
    this.content = this.middleslice.childNodes[1];
    this.border_r = this.middleslice.childNodes[2];
    
   
    if(!parseInt(this.options.posx))
      this.options.posx=-1;
    if(!parseInt(this.options.posy))
      this.options.posy=-1;
    this.setHeight(this.options.height);     
    this.setWidth(this.options.width);
    this.setPosX(this.options.posx);
    this.setPosY(this.options.posy);
    
    
    /*------------------- EFFECTS -----------------------*/
    
    
    //turn off opacity starteffect in draggable
    //because firefox gets slow when dragging divs with overflow:auto
    
    this.event("starteffects");
    this.positiondragger=new Draggable(this.element, 
      {
        handle:this.options.id+'_drag_handle',
        starteffect:this.startdrag.bind(this),
        zindex:500,
        endeffect: (this.stopdrag).bind(this)
      }
    );
    this.resizedragger=new Draggable(this.options.id+"_resize_handle", 
      {
        starteffect:(function() {this.event("resizestart");}).bind(this),
        change:(function(){this.event("resizing");}).bind(this),
        endeffect:(this.stopresize).bind(this)
      }
    );
    
    this.options.resizestartInternal=(function(){
      this.bringToTop();
    }).bind(this);
    
  
    
    
    this.options.resizingInternal=(function() {
      
      handleOffsets = Position.offsetParent(this.resizehandle);
     
      width = this.getResizeWidth();
      height = this.getResizeHeight();
     
      
      if (width < this.options.min_width){
          width = this.options.min_width;
        //"touch" the bottom slice div, else the bottomslice does not get redrawn under FF and KHTML
        this.fore=(!this.fore || this.fore==1)?-1:1;
        this.bottomslice.style.height=(this.bottomslice.offsetHeight+this.fore)+"px";
      }
      else{
        this.bottomslice.style.height=this.bottomslice.childNodes[0].style.height;
      } 
      if (height < this.options.min_height) height = this.options.min_height;
    
      this.setHeight(height);
      this.setWidth(width);
    
      
    }).bind(this);
    
    //"touch" the bottom slice div, else the bottomslice does not get redrawn under FF and KHTML            
    this.options.correctBottomSlice=function(target) {
        target.fore=(!target.fore || target.fore==1)?-1:1;
        target.bottomslice.style.height=(target.bottomslice.offsetHeight+target.fore)+"px";
    
    }
    
    
    this.options.resetResizeDraggerInternal= function(target) {
   
    this.maximized=false;
	   //check if resize_handler position is not where it should be.
    //this happens when win was made smaller than the minimum sizes
    
    h= target.bottomslice.childNodes[0].offsetHeight
      +target.middleslice.childNodes[0].offsetHeight
      +target.topslice.childNodes[0].offsetHeight
      -target.getResizeHeight();
    w=	target.bottomslice.offsetWidth-target.getResizeWidth();
    
    new Effect.MoveBy(target.resizehandle, h,w, {duration:0.0});
    
  }
  
  
  
    if(!window.max_zIndex ||window.max_zIndex<this.options.z_index) {
      window.max_zIndex=(this.options.z_index>0)?this.options.z_index:0; 
    }
    if(this.options.z_index==-1){
      this.bringToTop();
    }
    
    this.element.style.zIndex=this.options.z_index;
    new Effect.Appear(this.element,
      {
        duration:0.2,
        afterUpdate:(function(event) {
          if(this.options.is_hidden==false){
            this.element.style.visibility="visible";
          }
          this.event("stopinit");
        }).bind(this)
      }
    );
    
    if(this.options.is_minimized==true) {
      this.options.is_minimized=false;
      this.minimize();
    }
   
    if(this.options.stayontop==true) {
     
      this.options.stayontop=false;
      this.toggleStayOnTop();
    }
    
     if(this.options.scrollbars==true) {
       this.content.style.overflow="auto";
      
    }
    
    this.event("resetResizeDragger");

   
  }, //END INITIALIZE
  event: function(eventName) {
    if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
    if(this.options[eventName]) this.options[eventName](this);
  },
  setWidth:function(val) {
    this.options.width=val;
    //"touch"Ęthe value (for FF)
    this.element.style.width="0px";
    this.element.style.width=val+"px";
  },
  setHeight:function(val) {
    if(this.options.minimized)
      return;
    this.options.height=val;
    
    h=  val - this.topslice.childNodes[0].offsetHeight 
        - this.bottomslice.childNodes[0].offsetHeight;
   
    this.content.style.height=h+"px";
    this.border_l.style.height=h+"px";
    this.border_r.style.height=h+"px";
    
  },
  setPosX:function(val) {
    this.element.style.left=val+"px";
  },
  setPosY:function(val) {
     this.element.style.top=val+"px";
  },
  getResizeWidth: function() {
    
     return this.resizehandle.offsetLeft+this.resizehandle.offsetWidth;
  },
  getResizeHeight: function() {
    
     return this.resizehandle.offsetTop+this.resizehandle.offsetHeight;
  },
  stopdrag:function(element)  {
    
    if(document.all) {
      windowWidth=document.body.offsetWidth-this.options.screen_safety_border;
      windowHeight=document.body.offsetHeight-this.options.screen_safety_border;
    }
    else {
      windowWidth=window.innerWidth-this.options.screen_safety_border;
      windowHeight=window.innerHeight-this.options.screen_safety_border;
    }
 
    var moveX=0;
    var moveY=0;
    var currentX=this.element.offsetLeft;
    var currentY=this.element.offsetTop;
    var width=this.getResizeWidth();
    var height=this.getResizeHeight();
    var border=this.options.screen_safety_border
   
    
    if(currentX+width<border)
      moveX=border-(currentX+width);
    else if(currentX>windowWidth-border)
      moveX=-border-(currentX-windowWidth);
    
    if(currentY<border)
      moveY=-currentY;
    else if(currentY>windowHeight-border)
      moveY=-border-(currentY-windowHeight);
     
    
    saveposev=function(){
      this.options.posx=currentX;
      this.options.posy=currentY;
      this.event("stopdrag");     
    }.bind(this);
    
    if(moveX!=0 || moveY!=0) {
      new Effect.MoveBy(
        this.element,
        moveY,
        moveX,
        {	
          duration:0.2,  
          endeffect:saveposev
        }
      );
      
    }
    else {
      saveposev();
    }
    
 
	}
  
 ,
  stopresize:function(){
   
    this.event("resetResizeDragger");
    this.event("stopresize");
    
  },
 
  close:function() {
  
   
   if(this.closing)
     return;
   
   this.event("close");
  
   this.closing=true;
  
    new Effect.Fade(
     this.element,
      { duration:0.2,
        afterFinish:(function(event) {
          Element.remove(this.element);
        }).bind(this)
      }
    );
    

  },

  hide: function() {
    this.element.style.visibility="hidden";
  },

  show: function() {
    this.bringToTop();
    this.element.style.visibility="visible";
  },

  show_tab1: function() {
    this.bringToTop();
    this.buttab1.src="../images/but_1a.gif";
    this.buttab2.src="../images/but_2b.gif";
    this.content.innerHTML=this.tab1.innerHTML;
  },

  show_tab2: function() {
    this.bringToTop();
    this.buttab1.src="../images/but_1b.gif";
    this.buttab2.src="../images/but_2a.gif";
    this.content.innerHTML=this.tab2.innerHTML;
  },

  bringToTop:function() {

    if(this.options.stayontop==false && this.options.z_index<window.max_zIndex) {
      this.element.style.zIndex=++window.max_zIndex;
      this.options.z_index=this.element.style.zIndex;
     
    }
  },
  toggleStayOnTop:function() {
   if(this.options.stayontop==false) {
      this.options.stayontop=true;
      this.element.style.zIndex=990;
    }
    else {
       this.options.stayontop=false;
       this.bringToTop();
    }
    
  },
  minimize:function() {
    this.bringToTop();
    if(!this.fader.currentlyFading) {
      
      //we mustn't blind up while blinding down
      this.currentlyFading=true;
      
      if(this.options.is_minimized==true) {
        
        this.options.is_minimized=false;
        new Effect.BlindDown(
          this.fader ,  
          {
            afterFinish:(function(event){
              this.currentlyFading=false;
				      this.event("resetResizeDragger");
              this.event("unminimized");            
            }).bind(this),
            afterUpdate:(function(event){
              this.event("correctBottomSlice");
            }).bind(this)
          }
        );
        
      }
      else {
        this.options.is_minimized=true;
        
        new Effect.BlindUp(
            this.fader,
            { 
              afterFinish:(function(event){
                this.currentlyFading=false;
                this.event("resetResizeDragger");
                this.event("minimized");
              }).bind(this),
              afterUpdate:(function(event){
                  this.event("correctBottomSlice")
                }).bind(this)
            }
        );
      }
    }
    this.event("minimize");
  },
  maximize:function() {
    this.bringToTop();
     if(this.fader.currentlyFading)
       return;
     
   
    
     if(this.options.is_minimized==true) {      
       
          this.options.is_minimized=false;
          new Effect.BlindDown(this.fader,{afterFinish:(function() {this.maximize();}).bind(this)});
          return;
     }
      
   
    if(this.maximized) {
      
      this.fader.currentlyFading=true;
            
      
     
     this.event("maximize");
     
      new Effect.MoveBy( 
                 this.element, 
                 this.preMaxDims[1],
                 this.preMaxDims[0],
                 { duration:0.2  }
              );
     
     midh=(this.preMaxDims[3]-this.topslice.childNodes[0].offsetHeight-this.bottomslice.childNodes[0].offsetHeight);
     contenth=midh/this.middleslice.childNodes[0].offsetHeight*100;
     s_opts={scaleX:false, scaleContent:false, duration:0.2};
     new Effect.Scale( this.border_l,contenth, s_opts);
     new Effect.Scale( this.content, contenth, s_opts);
     new Effect.Scale( this.border_r,contenth, s_opts);
     
     new Effect.Scale( this.element,this.preMaxDims[2]*100/this.element.offsetWidth, 
        { 
          scaleY:false, 
          afterFinish:(function() {
              this.event("resetResizeDragger");
              this.event("maximized");
              this.fader.currentlyFading=false;
              
              this.maximized=false;
               this.event("correctBottomSlice");
              
            }).bind(this),  
          scaleContent:false,
          duration:0.2
        }
     );
     
    }
    else {
      
      this.fader.currentlyFading=true;
      if(document.all) {
        windowWidth=document.body.offsetWidth-20;
        windowHeight=document.body.offsetHeight-20;
      }
      else {
        windowWidth=window.innerWidth;
        windowHeight=window.innerHeight;
      }
      
      new Effect.MoveBy( 
         this.element, 
         -this.element.offsetTop,
         -this.element.offsetLeft,
         { duration:0.2  }
      );
     endh=windowHeight-this.topslice.childNodes[0].offsetHeight-this.bottomslice.childNodes[0].offsetHeight;
     contenth=endh*100/this.middleslice.childNodes[0].offsetHeight;
     this.preMaxDims=[
        this.element.offsetLeft,
        this.element.offsetTop,
        this.element.offsetWidth,
        this.element.offsetHeight
        ];
     this.event("maximize");
     
     s_opts={scaleX:false, scaleContent:false, duration:0.2};
     new Effect.Scale( this.border_l,contenth, s_opts);
     new Effect.Scale( this.content, contenth, s_opts);
     new Effect.Scale( this.border_r,contenth, s_opts);
     new Effect.Scale( this.element,windowWidth*100/this.element.offsetWidth, 
        { 
          scaleY:false, 
          afterFinish:(function() {
              this.event("resetResizeDragger");
              this.event("maximized");
              this.fader.currentlyFading=false;
              
              this.maximized=true;
              this.event("correctBottomSlice");
            }).bind(this),  
          scaleContent:false,
          duration:0.2
        }
     );
    }
  },
  startdrag:function(event) {
     this.bringToTop();
     if(this.options.stayontop==true)
       this.positiondragger.originalZ=990;
     else
       this.positiondragger.originalZ=this.options.z_index;
     
     this.event("startdrag");
  }
  
}




AjaxWindow = Class.create();
Object.extend(Object.extend(AjaxWindow.prototype, Window.prototype), {
  initialize: function() {
  
     var options = Object.extend({
        id:-1,
        name:"noname",
        min_width:100,
        min_height:100,
        screen_safety_border:20,
        width:100,
        height:100,
        posx:100,
        posy:100,
        z_index:0,
        stopdragInternal: this.saveWindow.bind(this),
        stopresizeInternal: this.saveWindow.bind(this),
        maximizedInternal: this.saveWindow.bind(this),
        minimizedInternal: this.saveWindow.bind(this),
        unminimizedInternal: this.saveWindow.bind(this),
        closeInternal: this.closeWindow.bind(this),
        saveUrl:"/windows/save",
        closeUrl:"/windows/close",
        highlightColor:"#F7F0DE",
        button_dirty_url:"/skins/minimal/but_dirty.gif",
        button_clean_url:"/skins/minimal/but_clean.gif"
        
      }, arguments[0] || {});
      this.options = options;
      
      //place window randomly
      if(this.options.posx==-1)
        this.options.posx=Math.floor(Math.random()*(window.innerWidth - this.options.width));
      if(this.options.posy==-1)
        this.options.posy=Math.floor(Math.random()*(window.innerHeight - this.options.height));
      
      //hmm, konqueror fix. Too lazy to figure out what goes wrong here
      if(this.options.posx<=0) this.options.posx=this.options.posx*-1;
      if(this.options.posy<=0) this.options.posy=this.options.posy*-1;
        
      this.start();
  },
  saveWindow:function() {
    
    if(this.closing)
      return;
    
    window.document.images["button_dirty_"+this.options.id].src=this.options.button_dirty_url;
   
    
    new Ajax.Updater(
        'loader',
        this.options.saveUrl, 
        { 
          asynchronous:true, 
          method:'post',
          insertion:Insertion.Top,
          parameters:'id='+this.options.id+'&json='+encodeURIComponent(optionsToJson(this.options)),
          onComplete:(function(){ 
              if(window.document.images["button_dirty_"+this.options.id])
             window.document.images["button_dirty_"+this.options.id].src=this.options.button_clean_url;
          }).bind(this),
          onSuccess:handleAjaxResponse
          
        }
        ); 
    
        
  },
  closeWindow:function() {

 if(this.closing)
    return;
  this.closing=true;

  
  new Ajax.Updater(
        'loader',
        this.options.closeUrl, 
        { 
          asynchronous:true, 
          method:"post",
          parameters:'id='+this.options.id,
          insertion:Insertion.Top,
          onSuccess:handleAjaxResponse
        }
        ); 
    
  }
});








