////////////////////////////////////////////////////////////////////////////////
// Tree Manager.
//
// Notes:
// + If JavaScript disabled, the tree will be fully expanded.
//
// Author: Nick Pope <nick@retiarius-ltd.co.uk>
// Change Log:
// + 200706291820 | 0.1.0 | Initial version
////////////////////////////////////////////////////////////////////////////////
var Tree = { 
  initialise: function() {
    for (var i = 0; i < arguments.length; i++) {
      // TODO: Throw error if tree is child element of another!
      var t = $(arguments[i].id);
      var t = arguments[i].elem ? arguments[i].elem : $(arguments[i].id);
      t.tree = arguments[i];
      t.tree.elem = t;
      t.tree.id = t.id;
      t.tree._collapse = t.tree.collapse;
      t.tree.collapse=function(e){e.ignoreAnim=true;t.tree._collapse(e);e.ignoreAnim=false;};
      t.tree._expand = t.tree.expand;
      t.tree.expand=function(e){e.ignoreAnim=true;t.tree._expand(e);e.ignoreAnim=false;};
      t.getElementsBySelector('ul').each(function(b) {
        var l = b.previous('a');
        l.tree = t.tree;
        l.hasClassName('expandible') && b.hide() && l.toggleClassName('expandible').toggleClassName('expandable');
        l.setStyle({ 'cursor': 'pointer' });
        l.observe('click', Tree.toggle.bindAsEventListener(Tree));
      });
      t.getElementsBySelector('a').each(function(l) {
        var s = l.next();
        if (s !== undefined && s.match('ul')) return;
        l.tree = t.tree;
        AjaxLinkifier.initialise({
          elem: l,
          update: t.tree.update,
          beforeUpdate: function(lnk) {Tree.reset(t); },
          afterSuccess: function(lnk) {l.addClassName('active'); TabBox.initialise({id:'tabbox',update:'tabbox',postUpdate:'reinit'}); },
          spinner: {elem:'tabbox',pos:'contents',posX:'.bdy',id:'ajax-spinner',src:'/img/icons/spinner-med.gif',height:24,width:24,alt:'Loading...'},
        });
      });
      // ensure that active item is visible
      t.getElementsByClassName('active').each(function(l) {
        l.ancestors().each(function(a) {
          if (a.match('ul')) {
            var b=a.previous('a');
            if (!b) return;
            b.tree.animate=false;
            Tree.toggle(b);
            b.tree.animate=true;
          }
        });
      });
    }
  },
  toggle: function(e) {
    var l = Event.element(e) || e;
    var b = l.next('ul');
    if (b.ignoreAnim) return;
    l.toggleClassName('collapsible').toggleClassName('expandable');
    l.tree.animate
      ? (b.visible() ? l.tree.collapse(b) : l.tree.expand(b))
      : b.toggle();
  },
  reset: function(t) {
    t.getElementsByClassName('active').invoke('removeClassName', 'active');
    $(t.tree.update).update();
  }
};

////////////////////////////////////////////////////////////////////////////////
// Ajax Linkifier - turns <a href="..."> into AJAX requests
//
// Notes:
// + If JavaScript disabled, links will work as normal.
//
// Author: Nick Pope <nick@retiarius-ltd.co.uk>, Dave Ingram <dave@retiarius-ltd.co.uk>
// Change Log:
// + 200707151420 | 0.1.0 | Initial version
////////////////////////////////////////////////////////////////////////////////
var AjaxLinkifier = {
  initialise: function() {
    for (var i = 0; i < arguments.length; i++) {
      var l = arguments[i].elem ? arguments[i].elem : $(arguments[i].id);
      l.ajaxlink = arguments[i];
      // l.link = t.tree;
      l.ajaxlink.url = l.getAttribute('href');
      l.ajaxlink.elem = l;
      l.setStyle({ 'cursor': 'pointer' }).removeAttribute('href');
      l.observe('click', AjaxLinkifier.link.bindAsEventListener(AjaxLinkifier));
    }
  },
  link: function(e) {
    var l = Event.element(e);
    if (l.ajaxlink.spinner) AjaxSpinner.init(l.ajaxlink.spinner);
    new Ajax.Request(l.ajaxlink.url, {
      method: 'get',
      onSuccess: function(tp) {
        if (l.ajaxlink.beforeSuccess) l.ajaxlink.beforeSuccess(l.ajaxlink, tp);
        if (l.ajaxlink.beforeUpdate)  l.ajaxlink.beforeUpdate(l.ajaxlink, tp);
        $(l.ajaxlink.update).update(tp.responseText);
        if (l.spinner) $(l.spinner.id).remove();
        if (l.ajaxlink.afterUpdate)   l.ajaxlink.afterUpdate(l.ajaxlink, tp);
        if (l.ajaxlink.afterSuccess)  l.ajaxlink.afterSuccess(l.ajaxlink, tp);
      },
      onFailure: function(tp) {
        if (l.ajaxlink.beforeFail)    l.ajaxlink.beforeFail(l.ajaxlink, tp);
        if (l.ajaxlink.beforeUpdate)  l.ajaxlink.beforeUpdate(l.ajaxlink, tp);
        // TODO: Finish nice error stuff...
        $(l.ajaxlink.update).update('Oops!');
        if (l.spinner) $(l.spinner.id).remove();
        if (l.ajaxlink.afterUpdate)   l.ajaxlink.afterUpdate(l.ajaxlink, tp);
        if (l.ajaxlink.afterFail)     l.ajaxlink.afterFail(l.ajaxlink, tp);
      }
    });
  },
};

var i1=new Image();
i1.src='/img/icons/spinner-med.gif';

var TabBox = {
  initialise: function() {
    for (var i = 0; i < arguments.length; i++) {
      var t = arguments[i].elem ? arguments[i].elem : $(arguments[i].id);
      t.tabs = arguments[i];
      // l.link = t.tree;
      t.tabs.id = t.id;
      t.tabs.elem = t;
      t.tabs.reinit=function() {TabBox.initialise(t.tabs)};

      if (t.tabs.postUpdate == 'reinit')
        t.tabs.postUpdate=t.tabs.reinit;

      t.getElementsBySelector('.hdr a').each(function(l) {
        AjaxLinkifier.initialise({
          elem: l,
          update: t.tabs.update,
          spinner: {elem:'tabbox',pos:'contents',posX:'.bdy',id:'ajax-spinner',src:'/img/icons/spinner-med.gif',height:24,width:24,alt:'Loading...'},
          afterSuccess: t.tabs.postUpdate,
        });
      });
    }
  },
};

var AjaxSpinner = {
  init: function() {
    for (var i = 0; i < arguments.length; i++) {
      var t = $(arguments[i].elem);
      t.spinner = arguments[i];
      t.spinner.elem = document.createElement('IMG');
      Element.extend(t.spinner.elem);
      t.spinner.elem.src=t.spinner.src;
      t.spinner.elem.height=t.spinner.height;
      t.spinner.elem.width=t.spinner.width;
      t.spinner.elem.id=t.spinner.id;
      var tmp=document.createElement('DIV'); tmp.appendChild(t.spinner.elem);

      if (t.spinner.pos=='before') {
        t.parentNode.insertBefore(t.spinner.elem, t);
      } else if (t.spinner.pos=='after') {
        if (t.nextSibling) {
          t.parentNode.insertBefore(t.spinner.elem, t.nextSibling);
        } else {
          t.parentNode.appendChild(t.spinner.elem);
        }
      } else if (t.spinner.pos=='contents') {
        if (t.spinner.posX) {
          // should only be one here
          t.getElementsBySelector(t.spinner.posX).each(function(el){el.setStyle({'text-align':'center'});el.update(tmp.innerHTML);});
        } else {
          t.update(t.spinner.elem.inspect());
        }
      } else if (t.spinner.pos=='replace') {
        t.replace(t.spinner.elem);
      } else {
        throw new Exception('No idea where to place spinner');
      }
    }
  }
}

// An animation effect for expanding a branch of the tree.
Effect.FadeExpand = function(e) {
  new Effect.BlindDown(e, { duration: 0.3 });
  new Effect.Opacity(e, { duration: 0.3, from: 0.0, to: 1.0 });
}

// An animation effect for collapsing a branch of the tree.
Effect.FadeCollapse = function(e) {
  new Effect.BlindUp(e, { duration: 0.3 });
  new Effect.Opacity(e, { duration: 0.3, from: 1.0, to: 0.0 });
}
