msWindowMaker = Class.create();
msWindowMaker.prototype =
{
  initialize: function (Url, Options)
  {
    this.Window = null;
    this.ClonedNode = null;
    
    this.WindowId = 'WinMaker' + Math.floor(Math.random() * Math.pow(10, 6));

    this.Options = {
      CloseImg: '/shared/img/win-close.png',
      MaxImg: '/shared/img/win-maximize.png',
      RestoreImg: '/shared/img/win-restore.png',
      ImgsHeight: 16,
      CourtainDiv: 'WindowMakerCourtain',
      CloseCallback: null,
      ClassDiv: 'WindowMakerDiv',
      ClassHeader: 'WindowMakerHeader',
      Maximized: false,
      AutoPrepare: false,
      FailureString: 'De server gaf een ongeldig resultaat terug. Probeer het later opnieuw.',
      DefaultTitle: 'Bezig met laden van de pagina...',
      Top: '10%',
      Left: '25%',
      Right: '25%',
      Bottom: 'auto',
      PopupAction: '' 
    };
    Object.extend(this.Options, Options || {});
    
    this.WinUrl = Url;

    this.isMaximized = false;
    this.isDraggable = (Scriptaculous.Version.gsub(/\./, '') >= 181) ? true: false;
    this.AjaxRequest = null;
    
    this.InitialDimensions = null;
    
    this.ImgsHeight = new Array();
    this.ImgsHeight.push(this.Options.ImgsHeight);

    if (this.Options.AutoPrepare == true) {
      this.Prepare();
    }
    else {
      Event.observe(window, 'load', this.Prepare.bindAsEventListener(this));  
    }
  },
  
  Prepare: function()
  {
    this.Window = new Element('DIV', {id: this.WindowId, 'class': this.Options.ClassDiv} );
    Element.setStyle(this.Window, {
      'position': 'absolute',
      'display': 'none',
      'top': this.Options.Top,
      'left': this.Options.Left,
      'right': this.Options.Right,
      'bottom': this.Options.Bottom,
      'width': '630px'
      //'overflow': 'auto'
      });

    this.CloseImg = new Image();
    this.CloseImg.src = this.Options.CloseImg;
    Event.observe(this.CloseImg, 'load', this.ImageLoaded.bindAsEventListener(this, this.CloseImg));
    Event.observe(this.CloseImg, 'click', this.Close.bindAsEventListener(this));
    
    
    this.MaxImg = new Image();
    this.MaxImg.style.display = 'none';
    
    this.MaxImg.src = this.Options.MaxImg;
    Event.observe(this.MaxImg, 'load', this.ImageLoaded.bindAsEventListener(this, this.CloseImg));
    Event.observe(this.MaxImg, 'click', this.ToggleView.bindAsEventListener(this));
    
    this.RestoreImg = new Image();
    this.RestoreImg.src = this.Options.RestoreImg;
    Event.observe(this.RestoreImg, 'load', this.ImageLoaded.bindAsEventListener(this, this.CloseImg));
    Event.observe(this.RestoreImg, 'click', this.ToggleView.bindAsEventListener(this));

    this.Header = new Element('DIV', {'class': this.Options.ClassHeader});
    Element.setStyle(this.Header, {
      'height': this.Options.ImgsHeight,
      'marginBottom': '5px',
      'padding': '5px'
      });
    Event.observe(this.Header, 'dblclick', this.ToggleView.bindAsEventListener(this));

    this.Controllers = new Element('DIV', {id: this.WindowId + 'Controllers'});
    Element.setStyle(this.Controllers, {
      'cssFloat': 'right',
      'cursor': 'pointer',
      'position': 'relative',
      'right': 0,
      'top': 0
      });

    this.Toggle = new Element('SPAN');
    this.Toggle.appendChild(this.isMaximized ? this.RestoreImg : this.MaxImg);

    this.Controllers.appendChild(this.Toggle);
    this.Controllers.appendChild(this.CloseImg);

    this.Title = new Element('DIV').update(this.Options.DefaultTitle);
    Element.setStyle(this.Title, {
      'cssFloat': 'left',
      'position': 'relative',
      'top': 0,
      'left': 0
      });

    this.Header.appendChild(this.Title);
    this.Header.appendChild(this.Controllers);
    this.Window.appendChild(this.Header);
    
    // I do not care what's in
    // the content will be inserted by SetContent
    this.ClonedNode = new Element('DIV'); 

    this.Window.appendChild(this.ClonedNode);
    
    this.Courtain = new Element('DIV', {
      id: this.WindowId + 'WindowMakerCourtain',
      'class': this.Options.CourtainDiv,
      title: 'Please use the window.'
      }).update(' ').hide();
    
    PageBody = document.getElementsByTagName('BODY')[0];
    PageBody.appendChild(this.Window);
    PageBody.appendChild(this.Courtain);
    
    this.Dimensions = this.Window.getDimensions();

    this.Courtain.style.zIndex = this.ComputeZindex() + 1;
    this.Window.style.zIndex = this.ComputeZindex() + 1;

    if (this.isDraggable && 1==2)
    {
      this.DragableRef = new Draggable(this.Window, {zindex: (this.ComputeZindex() + 1)});  
    }
  },
  
  ComputeZindex: function()
  {
    var zIndex = 0;
    var elm = $$('*');
    for (var i = 0, st = elm.length; i < st; i++)
    {
      var tmpzi = parseInt(elm[i].style.zIndex);
      if (tmpzi > 0 && tmpzi > zIndex)
        zIndex = tmpzi;
    }

    return zIndex;
  },
  
  ImageLoaded: function (event, image)
  {
    this.ImgsHeight.push(image.height);
    Element.setStyle(this.Header, {
      'height': this.ImgsHeight.max() + 'px'
      });
  },
 
  Set: function(Content)
  {
    this.ClonedNode.update(Content);
  },
  
  Show: function()
  {
    this.Courtain.show();
    this.Window.show();

    this.CachedWatchEsc = this.WatchEsc.bindAsEventListener(this);
    Event.observe(document, 'keyup', this.CachedWatchEsc);
    
    this.AjaxRequest = new Ajax.Request(this.WinUrl,  {
      method: 'get',
      onSuccess: this.AjaxSuccess.bindAsEventListener(this),
      onFailure: this.AjaxFailure.bindAsEventListener(this)
    });
  },
  
  AjaxSuccess: function(r)
  {
    try {
      var response = r.responseText.evalJSON();
     
      this.Title.update(response.title);
      this.ClonedNode.update(response.content); 
    }
    catch (e) {
      this.AjaxFailure(r);
    }
  },
  
  AjaxFailure: function(r)
  {
    this.ClonedNode.update(this.Options.FailureString);
  },
  
  Refresh: function()
  {
    this.AjaxRequest = null;

    this.AjaxRequest = new Ajax.Request(this.WinUrl,  {
      method: 'get',
      onSuccess: this.AjaxSuccess.bindAsEventListener(this),
      onFailure: this.AjaxFailure.bindAsEventListener(this)
    });
  },
  
  ToggleView: function(event)
  {
    if (this.isMaximized)
    {
      // Restore
      Element.setStyle(this.Window, {
        'top':    this.Options.Top,
        'left':   this.Options.Left,
        'right':  this.Options.Right,
        'bottom': this.Options.Bottom,
        
        'width':  this.Dimensions.width + 'px',
        'height': this.Dimensions.height + 'px'
        });
      
      this.Toggle.removeChild(this.RestoreImg);
      this.Toggle.appendChild(this.MaxImg);
      
      this.isMaximized = false;

      if (this.isDraggable)
      {
        // Draggables.register(this.DragableRef);
      }
    }
    else
    {
      // Maximize
      Element.setStyle(this.Window, {
        'top': '2%',
        'left': '2%',
        'right': '2%',
        'bottom': '2%',
        
        'width':  '95%',
        'height': '95%'
        });
      
      this.Toggle.removeChild(this.MaxImg);
      this.Toggle.appendChild(this.RestoreImg);
      
      this.isMaximized = true;

      if (this.isDraggable)
      {
        // Draggables.unregister(this.DragableRef);
      }
    }
  },

  WatchEsc: function(event)
  {
    if(event.keyCode == Event.KEY_ESC)
    {
      this.Close();
    }
  },
  
  Close: function()
  {
    if (this.isMaximized)
    {
      this.ToggleView();
    }
    this.Courtain.hide();
    this.Window.hide();

    /**
     * TODO: Must find a real way to kill ongoing ajax requests. 
     */
    this.AjaxRequest = null;
    
    this.Title.update(this.Options.DefaultTitle);
    this.ClonedNode.update(); 
  },
  
  Save: function()
  {
    form = $$('.popup').first();
    
    new Ajax.Request(this.Options.PopupAction, {
      parameters: form.serialize(),
      method: 'post',
      onSuccess: this.Close.bindAsEventListener(this)
    });
  },
  
  Post: function()
  {
    new Ajax.Request(this.Options.PopupAction, {
      parameters: form.serialize(),
      method: 'post',
      onSuccess: this.AjaxSuccess.bindAsEventListener(this),
      onFailure: this.AjaxFailure.bindAsEventListener(this)
    });
  },
  
  setPopupAction: function (act)
  {
    this.Options.PopupAction = act;
  }
  
  

}
