// Copyright (c) 2008 Brian Anderson (banderson623@gmail.com)
// Made exclusively for http://amesCoLab.com, as part of the first open source to come
// out of the CoLab project in Ames Iowa.
//
// Please use this as you can! Its officially licensed under the 
//
// MIT License.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

var Bubblizer = Class.create({
  bubbles: [],
  initial_sources: [],
  steps: 0,
  max_vertical_pixels_per_step: 7,
  max_horizontal_pixels_per_step: 1,
  poppable: false,
  horizontal_wander_value: 5,
  step_speed_in_ms: 50,
  
  initialize: function(desired_count) {
    this.desired_count = desired_count;
    
    this.starting_height = $('logo').positionedOffset()[1] + 10;
    this.horizontal_center = ($('logo').getWidth() / 2) - 15;

    // Load up bubbles
    $$('img.bubble').each(function(bub_element){ this.initial_sources.push(bub_element.src);}.bind(this));
    
    this.tryToConvertToPNGSources();
    
    this.initial_bubble_count = this.bubbles.length;
    this.bubble_container = $$('img.bubble')[0].up();
        
    this.startAnimation();
    setTimeout(function(){this.slowlyAddBubbles()}.bind(this), 2000);
  },

  tryToConvertToPNGSources: function(){
    if(navigator.appName == 'Netscape'){
      this.initial_sources = this.initial_sources.collect(function(src){
        return src.replace(/.gif/,'.png');
      }.bind(this));
    }
  },

  slowlyAddBubbles: function(){
    this.addABubble();
    if(this.desired_count > this.bubbles.length){
      setTimeout(function(){this.slowlyAddBubbles()}.bind(this), ((Math.random() * 1000) + 500));
    } else {
      this.poppable = true;
    }
  },

  addABubble: function(){
    var bubble = new Element('img', { 'class': 'bubble', 
                                         src:  this.initial_sources[Math.floor(Math.random() * this.initial_sources.length)],
                                         border: 0,
                                         "style": "display:none;"});
    this.bubble_container.insert({bottom:bubble});
    this.resetBubble(bubble);
    this.bubbles.push(bubble);
    bubble.show();
  },

  positionEm: function(){
    this.bubbles.each(function(bubble){
      this.resetBubble(bubble);
    }.bind(this));
  },
  
  resetBubble: function(bubble){
    bubble.setOpacity(Math.random() + 0.25);
    this.reWanderizeVertical(bubble);
    bubble.setStyle({top: (this.starting_height - this.jiggle(10, false)) +"px", 
                     left:this.horizontal_center+ this.jiggle(10) +"px"});
  },
  
  showEm: function(){
    this.bubbles.invoke('show');
  },
    
  animationStep: function(){
    this.steps++;
    if(this.bubbles.length > 0){
      //do some random things....
      if(Math.random() > 0.8) this.reWanderize(this.aRandomBubble());
      if(this.poppable && Math.random() > 0.7) {this.popRandomBubble();this.addABubble();}
    
      this.bubbles.each(function(bubble){
        if(bubble.positionedOffset()[1] < -10){ this.resetBubble(bubble);}
        bubble.setStyle({top: this.newVerticalPosition(bubble) + "px",
                         left: this.newHorizontalPosition(bubble) + 'px'});
      }.bind(this));
    }   
    if(this.timer != false){
      this.timer = setTimeout(function(){this.animationStep()}.bind(this), this.step_speed_in_ms);
    }
  },
  
  aRandomBubble: function(){
    return this.bubbles[Math.floor(Math.random() * this.bubbles.length)];
  },
  
  popRandomBubble: function(){
    this.popBubble(this.aRandomBubble());
  },
  
  popBubble: function(bubble){
    bubble.hide();
    this.bubbles = this.bubbles.reject(function(bub){
      return bub == bubble;
    }.bind(this));
  },
  
  reWanderizeVertical: function(bubble){
    bubble.setAttribute('v_wander',0);
  },
  
  reWanderize: function(bubble){
    bubble.setAttribute('h_wander',0);
  },
  
  newHorizontalPosition: function(bubble){
    var wander = bubble.getAttribute('h_wander');
    if(wander == undefined || wander == null || wander == 0){
      wander = this.jiggle(this.horizontal_wander_value);
      bubble.setAttribute('h_wander',wander);
    }
    
    var movement = this.jiggle(this.max_horizontal_pixels_per_step * wander, false);
    return bubble.positionedOffset()[0] + movement;
  },
  
  newVerticalPosition: function(bubble){
    var wander = bubble.getAttribute('v_wander');
    if(wander == undefined || wander == null || wander == 0){
      wander = Math.round(Math.random() * this.max_vertical_pixels_per_step);
      bubble.setAttribute('v_wander', wander);
    }
    var movement = wander;
    
    return bubble.positionedOffset()[1] - movement;
  },
  
  jiggle: function(max_giggle){
    var negative = (Math.random() > 0.5) ? -1 : 1;
    if(arguments[1] == false) negative = 1;
    
    return Math.round(Math.random() * max_giggle) * negative;
  },
  
  startAnimation: function(){
    this.timer = setTimeout(function(){this.animationStep()}.bind(this), this.step_speed_in_ms);
  },
  
  stopAnimation: function(){
    clearTimeout(this.timer);
    this.timer = false;
  }
  
  
});

document.observe('dom:loaded', function(){
  window.b = new Bubblizer(10);
})
