var PopupWin = function (options)
{
  if (!options) return;
  this.options = {
    contentFunc: options.contentFunc,
    width: options.width || 100,
    bottomThreshold: options.bottomThreshold || 200,
    noEasyClosing: options.noEasyClosing
  }

  this.id = ++PopupWin.currentId;
}

PopupWin.currentId = 0;
PopupWin.windows = [];

PopupWin.prototype.init = function ()
{
  if (this.initialized) return;

  // this IFRAME is necessary to fix broken SELECTs in IE6 and flash movie overlapping
  if (Prototype.Browser.IE) {
    var ifr = document.createElement("iframe");
    ifr.src = "javascript:void(0)";
    ifr.style.width = this.options.width + "px";
    ifr.style.position = "absolute";
    ifr.style.zIndex = 909;
    ifr.style.border = "none";
    ifr.id = this.iframeId = "ifr-popupwin-" + this.id;
    Element.hide(ifr);
    document.body.appendChild(ifr);
  }

  var winEl = document.createElement("div");
  winEl.className = "popup-win";
  winEl.id = this.win = "popupwin-" + this.id;
  winEl.style.width = this.options.width + "px";
  winEl.style.position = "absolute";
  winEl.style.zIndex = 910;

  var closeEl = document.createElement("div");
  closeEl.className = "popup-win-close";
  winEl.appendChild(closeEl);

  var wrapperEl = document.createElement("div");
  wrapperEl.className = "popup-win-inner";
  wrapperEl.id = this.wrapper = "popupwrapper-" + this.id;
  winEl.appendChild(wrapperEl);

  Element.hide(winEl);
  document.body.appendChild(winEl);
  this.visible = false;
  PopupWin.windows.push(this);

  Event.observe(closeEl, 'click', this.hide.bind(this));
  this.initialized = true;
}

PopupWin.prototype.destroy = function ()
{
  PopupWin.windows = PopupWin.windows.without(this);
}

PopupWin.prototype.show = function (el)
{
  PopupWin.hidePopups();
  this.init();
  el = $(el);
  this.skipClick = true;
  setTimeout(
    function () { this.skipClick = false; }.bind(this),
    200);
  this.options.contentFunc(
    $(this.wrapper),
    function () {
      if (!this.visible)
      {
//        $(this.win).style.display = 'block';
//        if (this.iframeId) $(this.iframeId).style.display = 'block';
        new Effect.Appear(this.win, { duration: 0.4 });
        if (this.iframeId)
          setTimeout(function () {
            $(this.iframeId).style.display = 'block';
            this.adjustIframe();
          }.bind(this), 1000);
        this.visible = true;
      }
      if (el)
        this.adjustPosition(el);
    }.bind(this));
}

PopupWin.prototype.adjustPosition = function (el)
{
  el = $(el);
  var pos = Position.cumulativeOffset(el);
  var right = pos[0] + el.offsetWidth;
  var bottom = pos[1] + el.offsetHeight;
  var winHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight || 0; // FIXME
  var winEl = $(this.win);
  var scrollTop =
    document.all ? document.documentElement.scrollTop ||
    document.body.scrollTop || 0 : window.pageYOffset || 0;
  if (winHeight - this.options.bottomThreshold + scrollTop < bottom)
  {
    var popupBottom = pos[1];
    if (popupBottom - winEl.offsetHeight < scrollTop) popupBottom = scrollTop + winEl.offsetHeight;
    winEl.style.top = (popupBottom - winEl.offsetHeight) + "px";
  }
  else
  {
    if (bottom + winEl.offsetHeight > scrollTop + winHeight)
      bottom = scrollTop + winHeight - winEl.offsetHeight;
    winEl.style.top = bottom + "px";
  }
  winEl.style.left = Math.max(0, right - this.options.width) + "px";
}

PopupWin.prototype.adjustIframe = function ()
{
  if (!this.iframeId) return;

  var winEl = $(this.win);
  var ifr = $(this.iframeId);
  ifr.style.left = winEl.style.left;
  ifr.style.top = winEl.style.top;
  ifr.style.width = winEl.offsetWidth + "px";
  ifr.style.height = winEl.offsetHeight + "px";
}

PopupWin.prototype.hide = function ()
{
  if (this.visible)
  {
    Element.hide($(this.win));
    if (this.iframeId) Element.hide($(this.iframeId));
    this.visible = false;
  }
}

PopupWin.prototype.isVisible = function ()
{
  return this.visible;
}

PopupWin.prototype.handleDocClick = function (e)
{
  if (!this.visible || this.skipClick || this.options.noEasyClosing) return;

  var win = $(this.win);
  var el = Event.element(e);
  for (; el && el != document.body; el = el.parentNode) {
    if (el == win || Element.hasClassName(el, "calendar")) // skip clicks to popup windows and calendars
      return;
  }

  if (!Position.within($(this.win),
                       Event.pointerX(e),
                       Event.pointerY(e)))
    this.hide();
}

PopupWin.documentClick = function (e)
{
  this.windows.each(
    function (win) {
      win.handleDocClick(e);
    });
}

PopupWin.hidePopups = function ()
{
  this.windows.invoke("hide");
}

Event.observe(document, "click", PopupWin.documentClick.bindAsEventListener(PopupWin));
