/* Neutral.js
 * Depends on:
 *   Prototype
 * Not public domain */

var Applet = Class.create({
  initialize: function(id, element, method, progressBar) {
    this.id = id;
    this.element = element;
    this.method = method;
    this.progressBar = progressBar;
  },
  
  progress: function(percent, messages) {
    this.progressBar.update('Running Experiment...', percent, messages);
  },
  
  complete: function(result) {
    // IMPLEMENT: actually report results
    this.progressBar.update('Reporting Results...', -1, '');
    Neutral.appletComplete(this);
  }
});

var ProgressBar = Class.create({
  initialize: function(where) {
    this.bar = new Element('div', {'class': 'bar'});
    this.text = new Element('p');
    this.outer = new Element('div', {'class': 'outer'});
    this.inner = new Element('div', {'class': 'inner'});
    this.percent = new Element('div', {'class': 'percent'});
    this.pre = new Element('pre', {'class': 'hidden'});
    this.toggle = new Element('a', {
      'href': 'javascript:void(0);'
    }).update('View Messages');
    
    this.inner.setStyle({'width': '0%'});
    
    this.toggle.observe('click', function() {
      this.pre.toggleClassName('hidden');
      if (this.pre.hasClassName('hidden')) {
        this.toggle.update('View Messages');
      } else {
        this.toggle.update('Hide Messages');
      }
    }.bindAsEventListener(this));
    
    this.bar.insert(this.text);
    this.bar.insert(this.outer);
    this.outer.insert(this.percent);
    this.outer.insert(this.inner);
    this.bar.insert(this.toggle);
    this.bar.insert(this.pre);
    $(where).insert(this.bar);
  },
  
  update: function(title, percent, messages) {
    var msg = String(messages);
    if (Prototype.Browser.IE) {  msg = msg.replace(/\n/g, '<br/>'); }
    this.pre.insert(msg);
    this.text.update(String(title));
    if (percent < 0) {
      this.inner.addClassName('indeterminite');
      this.inner.setStyle({'width': '100%'});
      this.percent.update('');
    } else {
      this.inner.removeClassName('indeterminite');
      this.inner.setStyle({'width': percent + '%'});
      this.percent.update(percent + '% Complete');
    }
  }
});

var Neutral = function() {
  var applets = $H();
  var nextIdentifier = 0;
  
  return {
    init: function() {
      this.experimentNumber = 0;
      Event.observe($('start'), 'click', this.start.bindAsEventListener(this));
    },
    
    start: function() {
      $('information').addClassName('hidden');
      $('experiment').removeClassName('hidden');
      this.getExperiments();
    },
    
    getExperiments: function() {
      var self = this;
      new Ajax.Request('/experiments/?number=' + this.experimentNumber++, {
        method: 'get',
        onSuccess: function(transport) {
          items = transport.responseText.evalJSON();
          items.each(function(item) {
            this.createApplet(item.url, item.method);
          }, self);
        }
      });
    },
    
    createApplet: function(url, method) {
      var identifier = nextIdentifier++;
      var element = new Element('applet', {
        'archive': url,
        'code': 'neutral',
        'width': '0',
        'height': '0',
        'mayscript': 'true'
      });
      element.insert(new Element('param', {
         'name': 'identifier',
         'value': identifier
      }));
      var applet = new Applet(identifier, element, method,
                              new ProgressBar($('progress')));
      applet.progressBar.update('Loading Java Applet...', -1, '');
      
      applets.set(identifier, applet);
      $('applets').insert(element);
    },
    
    applet: function(identifier) { return applets.get(identifier); },
    
    appletComplete: function(applet) {
      applets.unset(applet.id);
      if (applets.size() == 0) { this.getExperiments(); }
      setTimeout(function() {
        applet.progressBar.update('Complete!', 100, '');
      }, 1000);
    }
  };
}();

var UI = function() {
  return {
    toggleMessages: function(event) {
      $('messages').toggleClassName('hidden');
    }
  };
}();

// For applets to call
function appletMethod(identifier) {
  return Neutral.applet(identifier).method;
}
function appletProgress(identifier, percent, message) {
  return Neutral.applet(identifier).progress(percent, message);
}
function appletComplete(identifier, result) {
  return Neutral.applet(identifier).complete(result);
}

Event.observe(window, 'load', Neutral.init.bindAsEventListener(Neutral));
