if (typeof Prototype == 'undefined' || !Prototype.Version.match("1.6"))
   throw ("Prototype-UI library require Prototype library >= 1.6.0");

function getPageSize() {
   var xScroll, yScroll;
   if (window.innerHeight && window.scrollMaxY) {
      xScroll = document.body.scrollWidth;
      yScroll = window.innerHeight + window.scrollMaxY;
   } else if (document.body.scrollHeight > document.body.offsetHeight) { // all
      // but
      // Explorer
      // Mac
      xScroll = document.body.scrollWidth;
      yScroll = document.body.scrollHeight;
   } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla
      // and Safari
      xScroll = document.body.offsetWidth;
      yScroll = document.body.offsetHeight;
   }
   var windowWidth, windowHeight;
   if (self.innerHeight) { // all except Explorer
      windowWidth = self.innerWidth;
      windowHeight = self.innerHeight;
   } else if (document.documentElement
      && document.documentElement.clientHeight) { // Explorer 6 Strict
      // Mode
      windowWidth = document.documentElement.clientWidth;
      windowHeight = document.documentElement.clientHeight;
   } else if (document.body) { // other Explorers
      windowWidth = document.body.clientWidth;
      windowHeight = document.body.clientHeight;
   }

   // for small pages with total height less then height of the viewport
   if (yScroll < windowHeight) {
      pageHeight = windowHeight;
   } else {
      pageHeight = yScroll;
   }

   // for small pages with total width less then width of the viewport
   if (xScroll < windowWidth) {
      pageWidth = windowWidth;
   } else {
      pageWidth = xScroll;
   }

   arrayPageSize = new Array(pageWidth, pageHeight, windowWidth, windowHeight)
   return arrayPageSize;
}

Element.addMethods( {
   appendText : function(element, text) {
      element = $(element);
      element.appendChild(document.createTextNode(String.interpret(text)));
      return element;
   }
})

Object
   .extend(
      document.viewport,
      {
         // Alias this method for consistency
         getScrollOffset : document.viewport.getScrollOffsets,

         setScrollOffset : function(offset) {
            Element.setScrollOffset(
               Prototype.Browser.WebKit ? document.body
               : document.documentElement, offset);
         },
         getScrollDimensions : function() {
            return Element
            .getScrollDimensions(Prototype.Browser.WebKit ? document.body
               : document.documentElement);
         },
         getDimensions : function() {
            var dimensions = {};
            var B = Prototype.Browser;
            $w('width height')
            .each(function(d) {
               var D = d.capitalize();
               // HACK_HN START
               // alert(document.compatMode + "\n" +
               // navigator.userAgent);
               if (B.IE) {
                  if (navigator.appVersion
                     .indexOf("MSIE 6") > -1) {
                     dimensions[d] = (document.compatMode == 'CSS1Compat') ? document.documentElement['client' + D]
                     : document.body['client' + D];
                  } else {
                     dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D]
                     : (B.Opera) ? document.body['client' + D]
                     : document.documentElement['client' + D];
                  }
               } else {
                  dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D]
                  : (B.Opera) ? document.body['client' + D]
                  : document.documentElement['client' + D];
               }
            // HACK_HN END
            });
            return dimensions;
         }
      });

Window = Class
   .create( {
      initialize : function(domId, options) {
         /***************************************************************
				 * 
				 * Should be moved to window manager Create overlay
				 */
         this.options = Object
         .extend( {
            visible : false,
            useEffects : true,
            id : domId,
            title : options.header ? options.header : "Info",
            content : options.content,
            className : options.className ? options.className
            : "topdk",
            contentClassName : options.contentClassName ? options.contentClassName
            : "",
            width : options.width ? options.width : "100",
            height : options.height,
            headerIcon : options.headerIcon ? options.headerIcon : "",
            effectDuration: options.effectDuration ? options.effectDuration : 0.3
         });
         this.container = options.container ? options.container
         : document.body;
         this.name = domId;
         this.liftEvent = this.lift.bindAsEventListener(this);
         this.dropEvent = this.drop.bindAsEventListener(this);
         this.mouseMoveEvent = this.move.bindAsEventListener(this);
         this.useOverlay = true;
         this.useHeader = true;
         return this;
      },
      createDom : function() {
         if (this.useOverlay) {
            this.overlay = new Element("div", {
               className : this.options.className + "_overlay",
               id : this.options.id + '_overlay'
            });

            this.container.appendChild(this.overlay);
         }
         /* Create the main window itself */
         this.mainWindow = new Element("div", {
            className : this.options.className,
            id : this.options.id
         });
         this.mainWindow.style.top = (this.options.top ? parseInt(this.options.top)
            : 100) + 'px';
         this.mainWindow.style.left = (this.options.left ? parseInt(this.options.left)
            : 100) + 'px';
         if (this.useHeader) {
            /* Create header with close icon */
            this.header = new Element("div", {
               className : "header",
               id : this.options.id + "_header"
            });
            this.closeElement = new Element("a", {
               className : "close"
            });
            this.header.appendChild(this.closeElement);
            this.headerText = new Element("div", {
               className : "header_text"
            });

            if (this.options.headerIcon) {
               this.headerIcon = new Element("div", {
                  className : "header_icon"
               });
               this.headerIcon.style.background = 'url(' + this.options.headerIcon + ') no-repeat';
               this.header.appendChild(this.headerIcon);
            }

            this.header.appendChild(this.headerText);
            this.header.observe('mousedown', this.liftEvent);
            this.mainWindow.appendChild(this.header);
            this.closeElement.observe('click', this.hidePopUp
               .bind(this));
         }

         // this.contentFrame = new Element( "div", { className:
         // "content_frame", id: this.options.id+"_content"} );
         this.content = new Element("div", {
            className : "content",
            id : this.options.id + "_content_wrapper"
         });

         this.content.style.width = (this.options.width ? parseInt(this.options.width)
            : 100) + 'px';
         this.content.style.height = (this.options.height ? parseInt(this.options.height)
            : 100) + 'px';
         cName = 'content_container';
         if (this.options.contentClassName) {
            cName = cName + " " + this.options.contentClassName;
         }
         this.content.style.position = "relative";
         
         this.contentContainterId = this.options.id + "_content";
         this.contentContainer = new Element("div", {
            className : cName,
            id : this.contentContainterId
         });
         this.contentContainer.style.position = "relative";
         this.contentContainer.style.top = "0px";
         this.contentContainer.style.width = parseInt(this.content.style.width)
         - 25 + "px";
         this.contentContainer.style.left = "0px";
         this.content.show();
         this.contentContainer.show();

         /**
				 * Create navigation items
				 */
         this.contentNav = new Element("div", {
            className : 'content_nav',
            id : this.options.id + "_nav"
         });
         this.Up = new Element("div", {
            className : 'content_up',
            id : this.options.id + "_up"
         });

         this.Up.observe('mouseover', this.scrollUpMouseActivated
            .bind(this));
         this.Up.observe('mouseout', this.scrollUpMouseRelease
            .bind(this));

         this.Down = new Element("div", {
            className : 'content_down',
            id : this.options.id + "_down"
         });
         this.Down.style.top = parseInt(this.content.style.height) - 40
         + "px";
         this.Down.observe('mouseover', this.scrollDownMouseActivated
            .bind(this));
         this.Down.observe('mouseout', this.scrollDownMouseRelease
            .bind(this));
         this.contentNav.appendChild(this.Up);
         this.contentNav.appendChild(this.Down);
         this.content.appendChild(this.contentNav);

         /* Append the divs */

         this.content.appendChild(this.contentContainer);
         this.mainWindow.appendChild(this.content);

         /* Define observers */

         if (this.useOverlay) {
            this.overlay
            .observe('mousedown', this.hidePopUp.bind(this));
         }
      },
      setHeader : function(title) {
         this.options.title = title;
      },
      setContent : function(content) {
         this.options.content = content;
      },
      center : function() {
         pos = this.computeCenter( {
            height : parseInt(this.content.style.height),
            width : parseInt(this.content.style.width)
         });
         this.moveTo(parseInt(pos.top), parseInt(pos.left));
      },
      updateContent : function() {
         this.contentContainer.innerHTML = this.options.content;
      },
      showCenter : function() {
         this.show();
         this.center();
      },
      showAt : function(pos) {
         if (pos) {
            this.show();
            this.moveTo(pos[0], pos[1]);
         }
      },
      show : function() {
         if (!this.options.visible) {
            this.createDom();
            this.container.appendChild(this.mainWindow);
            this.options.visible = true;
         }

         if (this.options.top) {
            this.mainWindow.style.top = this.options.top;

         }
         if (this.options.left) {
            this.mainWindow.style.left = this.options.left;
         }
         if (this.useHeader) {
            // Style the header
            this.headerText.innerHTML = this.options.title;
            this.header.style.width = this.options.width + "px";
         }
         this.updateContent();

         if (this.useOverlay) {
            // Setup and display the overlay
            var arrayPageSize = getPageSize();
            this.overlay.style.height = arrayPageSize[1] + 'px';
            this.overlay.style.width = "100%";
            this.overlay.show();
         }

         // Ugly hack.. Show it, compute bottom and top hide and then
         // appear...
         this.mainWindow.show();
         offset = document.viewport.getScrollOffset();
         bottom = this.mainWindow.offsetTop  + this.mainWindow.offsetHeight;
         //right  = this.mainWindow.offsetLeft + this.mainWindow.offsetWidth + 20;

         // alert(this.contentContainer.offsetHeight);
         // Now, if the window is below the visible area, move it up a
         // notch
         dimensions = document.viewport.getDimensions();
         this.scrollMax = this.contentContainer.offsetHeight-parseInt(this.content.style.height);
         if (this.contentContainer.offsetHeight < parseInt(this.content.style.height)) {
            this.contentNav.hide();
            this.content.removeChild(this.contentNav);
         }

         if (bottom - offset.top > dimensions['height']) {
            newTop = dimensions['height']
            - this.mainWindow.offsetHeight + offset.top;
            this.moveTo(newTop, parseInt(this.mainWindow.style.left))
         }
         
         //alert(window.innerWidth + " : " + right);
         this.mainWindow.hide();
         this.appearElement(this.mainWindow);

         document.observe('keydown', this.respondToClick.bind(this));
      },
      fadeElement : function(element, doHide) {
         if ( doHide!=undefined ){
            return false;
         }
         if (this.options.useEffects)
            element.fade( {
               from: 1,
               to: 0,
               duration : this.options.effectDuration
            });
         else
            element.hide();
         return true;
      },
      appearElement : function(element,doHide) {
         if ( doHide!=undefined ){
            return false;
         }
         if (this.options.useEffects)
            element.appear( {
               from: 0.5,
               to: 1,
               duration : this.options.effectDuration
            });
         else
            element.show();
         return true;
      },
      hidePopUp : function(event) {
         if ( !this.options.visible )
            return false;
         this.fadeElement(this.mainWindow);
         if (this.useOverlay) {
            this.overlay.hide();
         }
         this.options.visible = false;
         document.stopObserving('keydown');
         return true;
      },
      lift : function(event) {
         // Get Mouseposition relative to left and top
         event.preventDefault();
         topPos = parseInt(this.mainWindow.style.top) ? parseInt(this.mainWindow.style.top)
         : 0;
         leftPos = parseInt(this.mainWindow.style.left) ? parseInt(this.mainWindow.style.left)
         : 0;
         this.diffY = parseInt(Event.pointerY(event)) - topPos;
         this.diffX = parseInt(Event.pointerX(event)) - leftPos;
         document.observe('mouseup', this.dropEvent);
         document.observe('mousemove', this.mouseMoveEvent);
         this.fadeElement(this.mainWindow, false);
      },
      drop : function(event) {
         this.appearElement(this.mainWindow, false);
         Event.stopObserving(document, 'mouseup', this.dropEvent);
         Event.stopObserving(document, 'mousemove', this.mouseMoveEvent);
      },
      move : function(event) {
         event.preventDefault();
         this.moveTo(parseInt(Event.pointerY(event)) - this.diffY,
            parseInt(Event.pointerX(event)) - this.diffX);
      },
      moveTo : function(x, y) {
         this.mainWindow.style.top = x + 'px';
         this.mainWindow.style.left = y + 'px';
      },
      moving : function(event) {
      },
      setPosition : function(x, y) {
         this.options.top = y + 'px';
         this.options.left = x + 'px';
      },
      computeCenter : function(size) {
         var viewport = document.viewport;
         area = document.viewport.getDimensions(),
         offset = document.viewport.getScrollOffset(),
         center = {
            top : (area.height - size.height) / 2,
            left : (area.width - size.width) / 2
         };
         return {
            top : parseInt(center.top + offset.top),
            left : parseInt(center.left + offset.left)
         };
      },
      setAjaxContent : function(url, options) {
         if (!options) {
            options = {};
         }
         var onComplete = options.onComplete;
         options.onComplete = (function(response, json) {
            this.setContent(response.responseText);
            this.updateContent();
            if (Object.isFunction(onComplete))
               onComplete(response, json);
         }).bind(this);

         new Ajax.Request(url, options);
         return this;
      },
      setIframeSrc : function(url){

         this.setContent("<iframe style='height:"+(this.options.height-20)+"px;' class=\"iframe\" src='"+url+"'/>");
      },
      noOverlay : function() {
         this.useOverlay = false;
      },
      noHeader : function() {
         this.useHeader = false;
      },
      disableEffects : function() {
         this.options.useEffects = false;
      },
      respondToClick : function(event) {
         stopEvent = false;
         if (event.keyCode == 27) {
            this.hidePopUp(event);
            stopEvent = true;
         } else if (event.keyCode == 40) {
            this.scrollDown();
            stopEvent = true;
         } else if (event.keyCode == 38) {
            this.scrollUp();
            stopEvent = true;
         } else {
         // alert(event.keyCode);
         }
         if (stopEvent)
            event.stop();
      },
      scrollUp : function() {
         if (parseInt(this.contentContainer.style.top) < 0)
            this.contentContainer.style.top = parseInt(this.contentContainer.style.top)
            + 25 + "px";
      },
      scrollDown : function() {
         if ( (-parseInt(this.contentContainer.style.top)) <= this.scrollMax)
            this.contentContainer.style.top = parseInt(this.contentContainer.style.top)
            - 25 + "px";
      },
      scrollUpMouseActivated : function() {
         this.scrollUpTimer = new PeriodicalExecuter(this.scrollUp
            .bind(this), 0.1);
      },
      scrollUpMouseRelease : function() {
         this.scrollUpTimer.stop();
         delete (this.scrollUpTimer);
      },
      scrollDownMouseActivated : function() {
         this.scrollDownTimer = new PeriodicalExecuter(this.scrollDown
            .bind(this), 0.1);
      },
      scrollDownMouseRelease : function() {
         this.scrollDownTimer.stop();
         delete (this.scrollDownTimer);
      },
      isVisible : function() {
         return this.options.visible;
      },
      setEffectDuration : function(duration)
      {
         this.options.effectDuration = duration;
      }
   })
