// xFenster r16a, Copyright 2004-2007 Michael Foster (Cross-Browser.com)
// Part of X, a Cross-Browser Javascript Library, Distributed under the terms of the GNU LGPL

function xFenster(clientId, iniTitle, iniUrl, iniX, iniY, iniW, iniH, miniW,
                  enMove, enResize, enMinimize, enMaximize, enClose,
                  fnMove, fnResize, fnMinimize, fnMaximize, fnClose, fnFocus, fnLoad,
                  clsCon, clsCli, clsTB, clsTBF, clsSB, clsSBF,
                  clsRI, clsNI, clsMI, clsOI, clsCI,
                  clsMask, bTransparentMask,
                  txtResize, txtMin, txtMax, txtRestore, txtClose)
{
  var me = this;

  // perhaps should be parameters
  var M = 1, B = 1;
  var M2 = 2*M, B2 = 2*B;

  // temporary?
  me.clsSB = clsSB;
  me.clsTB = clsTB;
  /*@cc_on
  @if (@_jscript_version <= 5.7)
    me.transMask = false;
  @else @*/
    me.transMask = bTransparentMask;
  /*@end @*/

  // Public Methods

  me.paint = function(dw, dh)
  {
    //msg(me, 'paint');////dbg///////
    me.conW += dw;
    me.conH += dh;
    xResizeTo(me.con, me.conW, me.conH);
    /*@cc_on
    @if (@_jscript_version <= 5.7) // IE7 and down
      xMoveTo(me.tbar, M, M);
      xWidth(me.tbar, me.conW - M2 - B2);
      xLeft(me.sbar, M);
      xWidth(me.sbar, me.conW - M2 - B2);
      xTop(me.sbar, me.conH - xHeight(me.sbar) - M - B2);
    @end @*/
    xMoveTo(me.client, M, M + me.tbar.offsetHeight);
    xResizeTo(me.client, me.conW - M2 - B2, me.conH - me.tbar.offsetHeight - me.sbar.offsetHeight - M2 - B2);
  };
  me.focus = function(e) // don't use 'this' here
  {
    //msg(me, 'focus');////dbg///////
    if (xFenster.focused != me && (!fnFocus || fnFocus(me))) {
      me.con.style.zIndex = xFenster.nextZ++;
      if (xFenster.focused) {
        xFenster.focused.tbar.className = xFenster.focused.clsTB;
        xFenster.focused.sbar.className = xFenster.focused.clsSB;
      }
      me.tbar.className = clsTBF;
      me.sbar.className = clsSBF;
      xFenster.focused = me;
    }
  };
  me.href = function(s)
  {
    //msg(me, 'href');////dbg///////
    var h = '';
    if (me.isIFrame) {
      if (me.client.contentWindow) {
        if (s) {me.client.contentWindow.location = s;}
        else h = me.client.contentWindow.location.href;
      }
      else if (typeof me.client.src == 'string') { // for Safari and Apollo on Windows
        if (s) {me.client.src = s;}
        else h = me.client.src;
      }
    }
    return h;
  };
  me.hide = function(e) // don't use 'this' here
  {
    //msg(me, 'hide');////dbg///////
    var i, o = xFenster.instances, z = 0, hz = 0, f = null;
    if (!fnClose || fnClose(me)) {
      me.con.style.display = 'none';
      xStopPropagation(e);
      if (me == xFenster.focused) {
        for (i in o) {
          if (o.hasOwnProperty(i) && o[i] && o[i].con.style.display != 'none' && o[i] != me) {
            z = parseInt(o[i].con.style.zIndex);
            if (z > hz) {
              hz = z;
              f = o[i];
            }
          }
        }
        if (f) {f.focus();}
      }
    }
  };
  me.show = function()
  {
    //msg(me, 'show');////dbg///////
    me.con.style.display = 'block';
    me.focus();
  };
  me.status = function(s)
  {
    //msg(me, 'status');////dbg///////
    if (s) {me.sbar.innerHTML = s;}
    else return me.sbar.innerHTML;
  };
  me.title = function(s)
  {
    //msg(me, 'title');////dbg///////
    if (s) {me.tbar.innerHTML = s;}
    else return me.tbar.innerHTML;
  };

  me.destroy = function()
  {
    //msg(me, 'destroy');////dbg///////
    try {
      me.hide();
      xRemoveEventListener(window, 'unload', winUnload, false);
      xRemoveEventListener(window, 'resize', winResize, false);
      me.con.parentNode.removeChild(me.con);
      winUnload();
    }
    catch (e) {
      alert('Error in destroy:\n\n' + e);////dbg///////
    }
  };

  // Private Event Listeners

  function dragStart()
  {
    //msg(me, 'dragStart');////dbg///////
    var i, o = xFenster.instances;
    for (i in o) {
      if (o.hasOwnProperty(i) && o[i] && !o[i].minimized && o[i].isIFrame) {
        if (!o[i].transMask) {o[i].client.style.display = 'none';}
        o[i].mask.style.display = 'block';
      }
    }
  }
  function dragEnd()
  {
    //msg(me, 'dragEnd');////dbg///////
    var i, o = xFenster.instances;
    for (i in o) {
      if (o.hasOwnProperty(i) && o[i] && !o[i].minimized && o[i].isIFrame) {
        if (!o[i].transMask) {o[i].client.style.display = 'block';}
        o[i].mask.style.display = 'none';
      }
    }
  }
  function barDrag(e, mdx, mdy)
  {
    //msg(me, 'barDrag');////dbg///////
    var x = me.con.offsetLeft + mdx;
    var y = me.con.offsetTop + mdy;
    if (!fnMove || fnMove(me, x, y)) {
      me.con.style.left = x + 'px';
      me.con.style.top = y + 'px';
    }
  }
  function resDrag(e, mdx, mdy)
  {
    //msg(me, 'resDrag');////dbg///////
    if (!fnResize || fnResize(me, me.client.offsetWidth + mdx, me.client.offsetHeight + mdy)) {
      me.paint(mdx, mdy);
    }
  }
  function maxClick()
  {
    //msg(me, 'maxClick');////dbg///////
    var w, h, i, t, r;
    if (me.minimized) {
      minClick();
    }
    if (me.maximized) {
      w = rW;
      h = rH;
      i = clsMI;
      t = txtMax || '';
      r = 'block';
    }
    else {
      w = xClientWidth() - 2;
      h = xClientHeight() - 2;
      i = clsOI;
      t = txtRestore || '';
      r = 'none';
    }
    if (!fnMaximize || fnMaximize(me, w - M2 - B2, h - me.tbar.offsetHeight - me.sbar.offsetHeight - M2 - B2)) {
      if (me.maximized) { // restore
        xMoveTo(me.con, rX, rY);
      }
      else { // maximize
        rW = me.con.offsetWidth;
        rH = me.con.offsetHeight;
        rX = me.con.offsetLeft;
        rY = me.con.offsetTop;
        xMoveTo(me.con, xScrollLeft(), xScrollTop());
      }
      me.mbtn.className = i;
      me.mbtn.title = t;
      if (me.rbtn) {me.rbtn.style.display = r;}
      me.maximized = !me.maximized;
      me.conW = w;
      me.conH = h;
      me.paint(0, 0);
    }
  }
  function minClick()
  {
    //msg(me, 'minClick');////dbg///////
    var w, h, i, t, r;
    if (me.maximized) {
      maxClick();
    }
    if (me.minimized) {
      w = rW;
      h = rH;
      i = clsNI;
      t = txtMin || '';
      r = 'block';
    }
    else {
      w = miniW;
      h = me.tbar.offsetHeight + me.sbar.offsetHeight + 6;
      i = clsOI;
      t = txtRestore || '';
      r = 'none';
    }
    if (!fnMinimize || fnMinimize(me)) {
      if (!me.minimized) {
        rW = me.con.offsetWidth;
        rH = me.con.offsetHeight;
        rX = me.con.offsetLeft;
        rY = me.con.offsetTop;
      }
      me.nbtn.className = i;
      me.nbtn.title = t;
      if (me.rbtn) {me.rbtn.style.display = r;}
      me.minimized = !me.minimized;
      me.conW = w;
      me.conH = h;
      me.paint(0, 0);
    }
  }
  function winResize()
  {
    //msg(me, 'winResize');////dbg///////
    if (me.maximized) {
      xResizeTo(me.con, 100, 100); // ensure fenster isn't causing scrollbars
      xMoveTo(me.con, xScrollLeft(), xScrollTop());
      me.conW = xClientWidth() - 2;
      me.conH = xClientHeight() - 2;
      me.paint(0, 0);
    }
  }
  function winUnload()
  {
    //msg(me, 'winUnload');////dbg///////
    me.con.onmousedown = me.con.onclick = null;
    if (me.nbtn) me.nbtn.onclick = null;
    if (me.mbtn) me.mbtn.onclick = me.tbar.ondblclick = null;
    if (me.cbtn) me.cbtn.onclick = me.cbtn.onmousedown = null;
    xFenster.instances[clientId] = null;
    me = null;
  }

  // Constructor Code

  xFenster.instances[clientId] = this;

  // public properties
  me.con = null;  // outermost container
  me.tbar = null; // title bar
  me.sbar = null; // status bar
  me.rbtn = null; // resize icon
  me.nbtn = null; // minimize icon
  me.mbtn = null; // maximize icon
  me.cbtn = null; // close icon
  me.mask = null;
  me.minimized = false;
  me.maximized = false;
  me.isIFrame = (typeof iniUrl == 'string');
  me.client = xGetElementById(clientId);

  // private properties
  var r;
  var rX, rY, rW, rH; // "restore" values

  // create elements
  if (!me.client) {
    me.client = document.createElement( me.isIFrame ? 'iframe' : 'div');
    me.client.id = clientId;
  }
  me.client.className += ' ' + clsCli;
  me.client.style.display = 'block';
  me.con = document.createElement('div');
  me.con.className = clsCon;
  if (enResize) {
    me.rbtn = document.createElement('div');
    me.rbtn.className = clsRI;
    me.rbtn.title = txtResize || '';
  }
  if (enMinimize) {
    me.nbtn = document.createElement('div');
    me.nbtn.className = clsNI;
    me.nbtn.title = txtMin || '';
  }
  if (enMaximize) {
    me.mbtn = document.createElement('div');
    me.mbtn.className = clsMI;
    me.mbtn.title = txtMax || '';
  }
  if (enClose) {
    me.cbtn = document.createElement('div');
    me.cbtn.className = clsCI;
    me.cbtn.title = txtClose || '';
  }
  me.tbar = document.createElement('div');
  me.tbar.className = clsTB;
  me.title(iniTitle);
  me.sbar = document.createElement('div');
  me.sbar.className = clsSB;
  me.status('&nbsp;');
  if (me.isIFrame) {
    me.mask = document.createElement('div');
    me.mask.className = clsMask;
  }
  // append elements
  me.con.appendChild(me.tbar);
  if (enMinimize) me.con.appendChild(me.nbtn);
  if (enMaximize) me.con.appendChild(me.mbtn);
  if (enClose) me.con.appendChild(me.cbtn);
  me.con.appendChild(me.client);
  me.con.appendChild(me.sbar);
  if (enResize) me.con.appendChild(me.rbtn);
  if (me.mask) me.con.appendChild(me.mask);
  document.body.appendChild(me.con);
  // final initializations
  me.conW = iniW;
  me.conH = iniH;
  xMoveTo(me.con, iniX, iniY);
  me.paint(0, 0);
  // position titlebar icons
  r = 2;
  if (me.cbtn) {
    me.cbtn.style.top = '2px';
    me.cbtn.style.right = r + 'px';
    r += me.cbtn.offsetWidth + 2;
  }
  if (me.mbtn) {
    me.mbtn.style.top = '2px';
    me.mbtn.style.right = r + 'px';
    r += me.mbtn.offsetWidth + 2;
  }
  if (me.nbtn) {
    me.nbtn.style.top = '2px';
    me.nbtn.style.right = r + 'px';
  }
  // register event listeners
  if (me.isIFrame) {
    me.href(iniUrl);
    if (fnLoad) xAddEventListener(me.client, 'load', function(){fnLoad(me);}, false);
    me.client.name = clientId;
  }
  if (enMove) xEnableDrag(me.tbar, dragStart, barDrag, dragEnd);
  if (enResize) xEnableDrag(me.rbtn, dragStart, resDrag, dragEnd);
  me.con.onmousedown = me.focus;
  if (enMinimize) me.nbtn.onclick = minClick;
  if (enMaximize) me.mbtn.onclick = me.tbar.ondblclick = maxClick;
  if (enClose) {
    me.cbtn.onclick = me.hide;
    me.cbtn.onmousedown = xStopPropagation;
  }
  xAddEventListener(window, 'unload', winUnload, false);
  xAddEventListener(window, 'resize', winResize, false);
  //
  me.con.style.visibility = 'visible';
  me.focus();

} // end xFenster object prototype

// xFenster static properties
xFenster.nextZ = 100;
xFenster.focused = null;
xFenster.instances = {};

