/*
 * Copyright (c) 2003 James Bailie <jimmy@jamesbailie.com>.
 * All rights reserved.
 *
 * Redistribution and use with or without modification, are permitted
 * provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * The name of James Bailie may not be used to endorse or promote
 * products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * num_fish is the number of fish in the animation.  It may be varied to
 * suit your taste.
 */

var num_fish       = 10,

    num_fish_left  = 6,
    num_fish_right = 6,
    num_turn       = 4,

    width          = window.innerWidth || document.documentElement.clientWidth,
    height         = window.innerHeight || document.documentElement.clientHeight,
    top            = 10,
    leftmost       = -100,
    rightmost      = width - 100,
    bottommost     = height - 300,

    right_trigger  = width / 2,
    left_trigger   = width / 3,

    total_leftright = num_fish_left + num_fish_right,
    total           = total_leftright + num_turn,

    pix             = new Array( total ),
    fish            = new Array( num_fish ),

    running         = false,
    swimming        = false;

function update_width()
{
    width          = window.innerWidth || document.documentElement.clientWidth;
    height         = window.innerHeight || document.documentElement.clientHeight;
    rightmost      = width - 100;
    bottommost     = height - 300;
    right_trigger  = width / 2;
    left_trigger   = width / 3;
}

function start()
{
   if ( running )
      return;

   running = true;
   animate();
}

function initialize_fish()
{
   var i = 0, j = 0;
   var body = document.getElementsByTagName( 'body' )[ 0 ];
   var html = '';

   for( ; i < num_fish; ++i )
   {
      html += '<div id="layer' + i +
              '" class="fish" style="position: absolute; display: none">' +
              '<img id="fish' + i +
              '" src="/fish0.png" style="border: none;" alt="" /></div>';
   }

   body.innerHTML += html;

   /*
    * Image objects to hold the fish frames.
    */

   for( i = 0; i < total; ++i )
      pix[ i ] = new Image();

   /*
    * Can't use a loop for the swim image assignments, since filenames are reused.
    */

   pix[ 11 ].src = '/fish0.png';
   pix[ 10 ].src = '/fish1.png';
   pix[ 9 ].src = '/fish2.png';
   pix[ 8 ].src = '/fish1.png';
   pix[ 7 ].src = '/fish0.png';
   pix[ 6 ].src = '/fish5.png';

   pix[ 5 ].src = '/fish6.png';
   pix[ 4 ].src = '/fish7.png';
   pix[ 3 ].src = '/fish8.png';
   pix[ 2 ].src = '/fish7.png';
   pix[ 1 ].src = '/fish6.png';
   pix[ 0 ].src = '/fish11.png';

   /*
    * We can use a loop to assign the turn images, however.
    */

   for( i = total_leftright; i < total; ++i )
      pix[ i ].src = '/turn' + j++ + '.png';

   for( i = 0; i < num_fish; ++i )
   {
      fish[ i ] = new fishie( i );
      fish[ i ].reset();
   }
}

function fishie( id )
{
   this.frame = 0;
   this.img   = document.getElementById( 'fish' + id );
   this.layer = document.getElementById( 'layer' + id );
   this.where = leftmost;
   this.dec   = id % num_fish + 2;
   this.turn  = 0;
   this.delay = 0;

   this.reset = reset;
   this.swim  = swim;
   this.move  = move;
   this.flip  = flip;
}

function reset()
{
   this.where = -( Math.round( Math.random() * 150 ) + 150 );
   this.turn  = 0;

   this.layer.style.display = 'block';
   this.layer.style.left = this.where + 'px';
   this.layer.style.top = ( top + Math.round( Math.random() * 200 )) + 'px';

   this.frame = Math.floor( Math.random() * num_fish_right ) + num_fish_right;
   this.img.src = pix[ this.frame ].src;
}

function swim()
{
   this.flip();
   this.move();
}

function flip()
{
   if ( this.turn >= total_leftright )
   {
      this.img.src = pix[ this.turn ].src;

      if ( ++this.delay < 2 )
         return;

      this.delay = 0;

      if ( ++this.turn == total )
      {
         this.turn = 1;
         this.delay = 0;
         this.frame = Math.floor( Math.random() * num_fish_left );
      }
   }
   else
   {
      var limit = ( this.turn ? num_fish_left : total_leftright );

      if ( ++this.delay < 3 )
         return;

      this.delay = 0;

      if ( ++this.frame == limit )
         this.frame = ( this.turn ? 0 : num_fish_left );

      this.img.src = pix[ this.frame ].src;
   }
}

function move()
{
   if ( this.turn == 0 )
   {
      if ( this.where > rightmost )
         this.turn = total_leftright;
      else
      {
         if ( this.where > right_trigger )
            this.where += this.dec;
         else
            this.where += 3;

         this.layer.style.left = this.where + 'px';
      }

      swimming = true;
   }
   else if ( this.turn == 1 )
   {
      /*
       * If the following condition fails, then the swimming global will be
       * left false.  All other possible paths through this function will
       * set swimming to be true, therefore if no fish remains onscreen (x
       * >= leftmost), no invocation of this method on any of the fish
       * objects will set swimming to be true.  This notifies the animate
       * function to reset the animation.
       */

      if ( this.where > leftmost )
      {
         if ( this.where > right_trigger || this.where < left_trigger )
            this.where -= this.dec;
         else
            this.where -= 3;

         this.layer.style.left = this.where + 'px';
         swimming = true;
      }
   }
   else
      swimming = true;
}

function animate()
{
   var i;

   swimming = false;

   for( i = 0; i < num_fish; ++i )
      fish[ i ].swim();

   if ( swimming )
      setTimeout( 'animate()', 20 );
   else
   {
      if (( top += 200 ) > bottommost )
         top = 10;

      for( i = 0; i < num_fish; ++i )
         fish[ i ].reset();

      running = false;
   }
}

window.onload = initialize_fish;
window.onresize = update_width;
