/*!*******************************************************************************
 *
 *  Runway10 (runway10.com)
 *  Copyright notice
 *
 *  (c) 2008-2009 Runway10 (r10JSCore@runway10.com)
 *  All rights reserved
 *
 *  This script is part of the Runway10 JS core library project or R10JSCore.
 *  The R10JSCore project is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  The GNU General Public License can be found at
 *  http://www.gnu.org/copyleft/gpl.html.
 *  A copy is found in the textfile GPL.txt and important notices to the license
 *  from the author is found in LICENSE.txt distributed with these scripts.
 *
 *  This script is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  This copyright notice MUST APPEAR in all copies of the script!
 *
 *********************************************************************************/

/*!*
 * Image cycler is a control that slides a series of images in the screen.
 * The images are show in a pre configured container
 */
ImageCycler = Class.create({
  
  /**
   * IT accepts an options object that defines the list of images objects
   * The image object define id, url, and image title
   */
  initialize: function(options) {
    this.options = Object.extend({ 
        container: 'container', images: [], index: 0, interval: 5000, shuffle: true,
        appearDuration: 2.0, fadeDuration: 2.0 
      }, options || {}
    )
    if (this.options.images.length > 1) {
      Event.observe(window, 'load', this.start.bind(this), false)
    }
  },
  
  getImage: function(index) {
    var image = this.options.images[index]
    var img = $(image.id)
    if (!img) {
      img = document.createElement("img")
      img.id = image.id
      img.src = image.url
      img.alt = image.title
      $(img).hide()
      $(this.options.container).appendChild(img)
    }
    return img  
  },
  
  swap: function() {
    var current = this.options.index++;
    if (this.options.index >= this.options.images.length) {
      this.options.index = 0;
    }  
    $(this.getImage(current)).fade({ duration: this.options.fadeDuration })
    var img = this.getImage(this.options.index)
    var swapper = this.update
    var swaptime = this.options.interval
    var appearDuration = this.options.appearDuration
    setTimeout(function() { 
      $(img).appear({ 
        afterFinish: function() { 
          setTimeout(swapper, swaptime)
        },
        duration: appearDuration
      })
    }, 0);
    this.prefetch()
  },
  
  prefetch: function() {
    var next = this.options.index + 1
    this.getImage(next >= this.options.images.length ? 0 : next)
  },
  
  start: function() {
    this.prefetch()
    if (this.options.shuffle) {
      var current = this.options.images[this.options.index]
      fisherYatesRandomize(this.options.images)
      this.options.index = $A(this.options.images).indexOf(current)     
    }
    this.update = this.swap.bind(this)
    setTimeout(this.update, this.options.interval)
  }

})

function fisherYatesRandomize( ary ) {
  var i = ary.length;
  if ( i == 0 ) return false;
  while ( --i ) {
    var j = Math.floor( Math.random() * ( i + 1 ) );
    var tempi = ary[i];
    var tempj = ary[j];
    ary[i] = tempj;
    ary[j] = tempi;
  }
}

MapController = Class.create({
  /**
   * This controller supports creating a map with the given address passes as part of the options
   * options == { address: "where to point the map", mapCanvas: "element where to pain the map" }
   */
  initialize: function(options) {
    if (options) {
      if (options.address && options.mapCanvas) {
        this.options = options
        this.geocoder = new google.maps.Geocoder();
        this.codeAddress(this.options.address)
      }
    }
  },
  codeAddress: function(address) {
    if (this.geocoder) {
      var controller = this;
      this.geocoder.geocode({ 'address': address }, function(results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
          if (status != google.maps.GeocoderStatus.ZERO_RESULTS) {
            controller.createMap(results[0].geometry.location)
          } else {
            // TODO Unable to validate the given address
            alert("Couldn't locate geolocation to define map")
          }
        } else {
          // TODO Invalidate server response
          alert("Geocode was not successful for the following reason: " + status);
        }
      });
    }
  },
  createMap: function(geoLocation) {
    if (!this.marker) {
      var myOptions = {
        zoom: 15,
        center: geoLocation,
        mapTypeId: google.maps.MapTypeId.ROADMAP
      }
      this.map = new google.maps.Map($(this.options.mapCanvas), myOptions);
      this.map.set_center(geoLocation);
      this.marker = new google.maps.Marker({ map: this.map, position: geoLocation });
    }
  }
})

CssHoverPrefetcher = Class.create({
  initialize: function() {
    $$('link[type="text/css"]').each(this.processLink.bind(this))
  },
  processLink: function(link) {
    new Ajax.Request(link.href, { onComplete: this.onStyle.bind(this)})
  },
  onStyle: function(res) {
    var control = this;
    res.responseText.match(CssHoverPrefetcher.expression).each(function(e) { control.prefetchUrl(e) } );
  },
  prefetchUrl: function(hover) {
    var url = hover.substring(4, hover.length - 1)
    img = document.createElement("img")
    img.src = url
    $(img).hide()
  }
})
CssHoverPrefetcher.expression = /url\(.*-hover\..*\)/g