var dd = {
  path : '/'
};

Prototype.Browser.IE6 = Prototype.Browser.IE && parseInt(navigator.userAgent.substring(navigator.userAgent.indexOf("MSIE")+5))==6;



Object.extend(Array.prototype, (function() {
  function sum(){
    return(!this.length) ? 0 : this.slice(1).sum() + ((typeof this[0]=='number') ? this[0] : 0);
  }

  return {
    sum : sum
  }
})());


Object.extend(Date.prototype, (function() {
  function isToday(){
    return this.isDate(new Date());
  }

  function isDate(date) {
    return (
      this.getFullYear() == date.getFullYear() &&
      this.getMonth() == date.getMonth() &&
      this.getDate() == date.getDate()
    );
  }

  function strftime(format) {
    var day = this.getDay(), month = this.getMonth();
    var hours = this.getHours(), minutes = this.getMinutes();
    
    return format.gsub(/\%([aAbBcdDHiImMpSwyY])/, function(part) {
      switch(part[1]) {
        case 'a': return $w("Sun Mon Tue Wed Thu Fri Sat")[day]; break;
        case 'A': return $w("Sunday Monday Tuesday Wednesday Thursday Friday Saturday")[day]; break;
        case 'b': return $w("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec")[month]; break;
        case 'B': return $w("January February March April May June July August September October November December")[month]; break;
        case 'c': return this.toString(); break;
        case 'd': return this.getDate(); break;
        case 'D': return this.getDate().toPaddedString(2, 10); break;
        case 'H': return hours.toPaddedString(2, 10); break;
        case 'i': return (hours === 12 || hours === 0) ? 12 : (hours + 12) % 12; break;
        case 'I': return ((hours === 12 || hours === 0) ? 12 : (hours + 12) % 12).toPaddedString(2, 10); break;
        case 'm': return (month + 1).toPaddedString(2, 10); break;
        case 'M': return minutes.toPaddedString(2, 10); break;
        case 'p': return hours > 11 ? 'PM' : 'AM'; break;
        case 'S': return this.getSeconds().toPaddedString(2, 10); break;
        case 'w': return this.getWeek(); break;
        case 'y': return (this.getFullYear() % 100).toPaddedString(2, 10); break;
        case 'Y': return this.getFullYear().toString(); break;
      }
    }.bind(this));
  }

  return {
    isDate : isDate,
    isToday : isToday,
    strftime : strftime
  }

})());


Object.extend(Event, (function(){
  var REGISTERABLE = $w('click mouseover mouseout mousedown mouseup');
  var cache = {};

  function getEventID(element) {
    if (element._prototypeEventID) return element._prototypeEventID[0];
    arguments.callee.id = arguments.callee.id || 1;
    return element._prototypeEventID = [++arguments.callee.id];
  }

  function getCacheForID(id) {
    return cache[id] = cache[id] || { };
  }

  function getWrappersForEventName(id, eventName) {
    var c = getCacheForID(id);
    return c[eventName] = c[eventName] || [];
  }

  function dispatch(e){
    var element = e.target;
    while(!e.stopped && element && element.nodeType == 1){
      var respondersForEvent = getWrappersForEventName(getEventID(element), e.type);
      if(respondersForEvent.length){
        l = i = respondersForEvent.length;
        do {
          respondersForEvent[l-i](e);
        }while(--i);
      }
      element = element.parentNode;
    }
  }

  function initialize(e){
    REGISTERABLE.each(function(eventName){
      document.observe(eventName, dispatch);
    });
  }

  document.observe('dom:loaded', initialize);


  function register(element, eventName, handler){
    var id = getEventID(element);
    var c = getWrappersForEventName(id, eventName);
    if (c.pluck("handler").include(handler)) return false;
    var wrapper = function(event){
      handler.call(element, event);
    };
    wrapper.handler = handler;
    c.push(wrapper);
    return wrapper;
  }

  return {
    register : function(element, eventName, callback){
      element = $(element);
      if(REGISTERABLE.include(eventName)){
        register(element, eventName, callback);
        return element
      }else{
        return Event.observe(element, eventName, callback);
      }
    },
    unregister : function(){

    }
  };
})());



Object.extend(Number.prototype, (function() {
  function isEven(){
    return (this%2==0);
  }
  function isOdd(){
    return (this%2!=0);
  }
  return {
    isEven : isEven,
    isOdd : isOdd
  }
})());


Object.extend(String.prototype, (function() {
  function toTitleCase(){
    return this.replace(/([\w&`'‘’"“.@:\/\{\(\[<>_]+-? *)/g, function(match, p1, index, title) {
      if (index > 0 && title.charAt(index - 2) !== ":" && match.search(/^(a(nd?|s|t)?|b(ut|y)|en|for|i[fn]|o[fnr]|t(he|o)|vs?\.?|via)[ \-]/i) > -1) return match.toLowerCase();
      if (title.substring(index - 1, index + 1).search(/['"_{(\[]/) > -1) return match.charAt(0) + match.charAt(1).toUpperCase() + match.substr(2);
      if (match.substr(1).search(/[A-Z]+|&|[\w]+[._][\w]+/) > -1 || title.substring(index - 1, index + 1).search(/[\])}]/) > -1) return match;
      return match.charAt(0).toUpperCase() + match.substr(1);
    });
  }

  function uncache(){
    return this+((this.indexOf('?')!=-1) ? '&' : '?')+'uncache='+new Date().getTime();
  }

  return {
    toTitleCase : toTitleCase,
    uncache : uncache
  };
})());


dd.util = {};


dd.util.Region = Class.create({
  initialize : function(t, r, b, l){
    this.cache = {};
    this.update(t, r, b, l);
    this.handler = this.fire.bindAsEventListener(this);
    if((b = document.body) && Object.isFunction($E)){
      $E(b, 'mouseenter', this.handler);
      $E(b, 'mouseleave', this.handler);
      $E(b, 'mouseover', this.handler);
      $E(b, 'mouseout', this.handler);
      $E(b, 'mousemove', this.handler);
      $E(b, 'mousedown', this.handler);
      $E(b, 'mouseup', this.handler);
      $E(b, 'click', this.handler);
    }
  },
  update : function(t, r, b, l){
    this.top = t;
    this.right = r;
    this.bottom = b;
    this.left = l;
  },
  contains : function(x, y){
    return (x >= this.left && x <= this.right && y >= this.top && y <= this.bottom);
  },
  intersect : function(region){
    var t = Math.max(this.top, region.top);
    var r = Math.min(this.right, region.right);
    var b = Math.min(this.bottom, region.bottom);
    var l = Math.max(this.left, region.left);
    if(b >= t && r >= l){
        return new dd.Region(t, r, b, l);
    } else {
        return false;
    }
  },
  observe : function(eventName, callback){
    this.cache[eventName] = this.cache[eventName] || $A();
    if(this.cache[eventName].include(callback)) return false;
    this.cache[eventName].push(callback);
  },
  fire : function(e){
    if(this.contains(e.clientX, e.clientY)){
      if(this.cache[e.type]){
        this.cache[e.type].invoke('call', this, e);
      }
    }
  }
});



dd.util.History = {};


/** 
 * class dd.util.History.Module
 * History module.
**/

dd.util.History.Base = function(){
  var _iframe;
  var _modules = $A();
  var _hash = '';
  var _initialState = {};  
  var _currentState = {};
  
  function _getHash(){
    return top.location.hash.substr(1);
  }
  
  function _setHash(hash){
    top.location.hash = hash;    
    if(Prototype.Browser.IE && _iframe){
      var doc = _iframe.contentWindow.document;
		  doc.open();
		  doc.write('<html><body id="state">' + hash + '</body></html>');
		  doc.close();
		}
  }
  
  function _checkState(hash){
    var changed;
    
    if(hash){
      var states = hash.toQueryParams();              
      _modules.each(function(module, i){
        var state = states[module];
        if(!state || state !== _currentState[module]){
          _currentState[module] = state;
          changed = true;
        }
      });
    }else{
      _modules.each(function(module, i){
        if(_currentState[module] !== _initialState[module]){
          _currentState[module] = _initialState[module];
          changed = true;
        }
      });
    }
    
    if(changed){
      document.fire('history:change', _currentState);
    }
    
  }
  
  function _setState(states){    
    var change = false;
    _modules.each(function(module, i){
      if(states[module] && (_currentState[module] == states[module])){
        delete states[module];
      }
    });

    if(Object.keys(states).size()===0){
      return false;
    }

    var hash = Object.toQueryString(Object.extend(Object.clone(_currentState), states));                    
    _setHash(hash);
  }
  
  document.observe('dom:loaded', function(e){    
    if(!Object.isUndefined(window.onhashchange) && (Object.isUndefined(document.documentMode) || document.documentMode > 7)) {
      window.onhashchange = function(){
        var hash = _getHash();
        if(hash !== _hash){
          _hash = hash;    
          _checkState(_hash);    
        }
      };
      var hash = _getHash();
      if(hash !== _hash){
        _hash = hash;    
        _checkState(_hash);    
      }
    }else if(Prototype.Browser.IE){
      // _iframe = new Element('iframe', {src: '/daydream/assets/html/history.html'}).setStyle({
      //   'height' : 0,
      //   'visibility' : 'hidden',
      //   'width' : 0
      // });
      // Element.insert(document.body, _iframe);
      
      _iframe = $('daydream-history');
      _iframe.setStyle({
        height : '0',
        visibility : 'visible',
        width : '0'
      });
      
      function checkIframe(){
      
        if(!_iframe.contentWindow.document){
          setTimeout(checkIframe, 10);
          return;
        }
      
        var iframeBody = _iframe.contentWindow.document.body;
        var _state = iframeBody ? iframeBody.innerText : null;
      
        new PeriodicalExecuter(function(){
          
          var hash = _getHash();

          var doc = _iframe.contentWindow.document;
          var iframeBody = doc.body;
          var state = iframeBody ? iframeBody.innerText : null;
          
          if(state !== _state){
            _hash = state;
            _checkState(state);
            top.location.hash = state;
          }else if(hash !== _hash){
            _hash = hash;
             doc.open();
             doc.write('<html><body id="state">' + hash + '</body></html>');
             doc.close();
          }
          
        
          // var doc = _iframe.contentWindow.document;    
          //         
          // if(doc && doc.body.id == 'state') {
          //   var state = doc.body.innerText;
          // }else{
          //   if(doc){      
          //     var state = _getHash();      
          //              doc.open();
          //              doc.write('<html><body id="state">' + state + '</body></html>');
          //              doc.close();            
          //   }else{
          //   
          //   }
          // }
          //         
          // if(state !== _hash){          
          //   _hash = state;
          //   _checkState(state);        
          //   top.location.hash = state;          
          // }
        
        }, 0.1);
      }
      
      checkIframe();
      
    }else{
      new PeriodicalExecuter(function(){        
        var hash = _getHash();
        if(hash !== _hash){
          _hash = hash;    
          _checkState(_hash);    
        }
      }, 0.1); 
    }
  });
  
  return {
    /**
     *  dd.util.History.fire() -> this
     **/
    fire : function(){      
      var state = {};
      state[arguments[0]]=arguments[1];
      
      _setState(state);
      return this;
    },
    /**
     *  dd.util.History.observe(eventName, callback) -> null
     **/
    observe : function(eventName, callback){
      document.observe(eventName, callback);
    },
    /**
     *  dd.util.History.register(name, initialState) -> null
     **/
    register : function(name, initialState){      
      if(!name && !initialState) return false;
      
      if(!_modules.include(name)){
        _modules.push(name);
        _initialState[name]=initialState;
        _currentState[name]=initialState;        
      }
    },
    getBookmarkedState : function(module){
      var hash = _getHash();
      if(hash){
        var state = hash.toQueryParams();
        return module ? (state[module] || null) : state;
      }
    },
    getState : function(module){
      return module ? _currentState[module] : _currentState;
    }
  }  
}();

/** 
 * class dd.util.History.Module
 * History module.
**/

dd.util.History.Module = Class.create({
  /**
   *  new dd.util.History.Module(name)
   *  - name (String): Name to use for the history module.
   *
   *  Creates a new `dd.util.History.Module`.
  **/
  initialize : function(name, state){
    this.cache = {};
    this.name = name;
    dd.util.History.Base.register(name, state);
    dd.util.History.Base.observe('history:change', this.dispatch.bindAsEventListener(this));
  },
  /**
   *  dd.util.History.Module.observe(eventName, callback) -> undefined
   *  - eventName (String): The history event to observe.
   *  - callback (Function): The callback to be executed.
   *
   *  Registers an event handler on this history module.
   **/
  observe : function(eventName, callback){
    this.cache[eventName] = this.cache[eventName] || $A();
    if(this.cache[eventName].include(callback)) return false;
    this.cache[eventName].push(callback);
  },
  fire : function(hash){
    dd.util.History.Base.fire(this.name, hash);
  },
  dispatch : function(e){
    var state = e.memo[this.name];
    if((state != this.state) && this.cache[e.eventName]){
      this.state = state;      
      this.cache[e.eventName].invoke('call', this, e);
    }
  },
  getState : function(){
    return dd.util.History.Base.getState(this.name);
  }
});

dd.ui = {};

dd.ui.Overlay = {};

dd.ui.Overlay.Base = Class.create({
  initialize : function(options){
    this.options = Object.extend({
      'className' : 'dd-ui-overlay',
      'opacity' : 1
    }, options||{});

    if(this.options.show && Object.isFunction(this.options.show)){
      this._show = this.options.show.bind(this);
    }

    if(this.options.hide && Object.isFunction(this.options.hide)){
      this._hide = this.options.hide.bind(this);
    }

    this.build();
  },
  build : function(){
    var style = {
      'left' : 0,
      'position' : Prototype.Browser.IE6 ? 'absolute' : 'fixed',
      'top' : 0,
      'zIndex' : 5000
    };

    this.element = new Element('div', {className : this.options.className}).setStyle(Object.extend({
    }, style)).hide();

    this.content = new Element('div', {className: 'dd-ui-overlay-base-content'});
    this.element.insert(this.content);

    document.body.appendChild(this.element);

    if(Prototype.Browser.IE6){
      
      this.iframe = new Element('iframe', {src: 'javascript:false'}).setStyle(Object.extend({
        'border' : 0,
        'opacity' : 0,
        'zIndex' : 4999
      }, style)).hide();

      document.body.appendChild(this.iframe);

      this.element.show = this.element.show.wrap(function(proceed){
        this.iframe.show();
        proceed();
      }.bind(this));

      this.element.hide = this.element.hide.wrap(function(proceed){
        proceed();
        this.iframe.hide();
      }.bind(this));
    }

    this.resize();
    Event.observe(window, 'resize', this.resize.bindAsEventListener(this));
  },
  resize : function(){
    var d = document.viewport.getDimensions();

    var ho = [
      parseInt(this.element.getStyle('margin-left'), 10),
      parseInt(this.element.getStyle('margin-right'), 10),
      parseInt(this.element.getStyle('padding-left'), 10),
      parseInt(this.element.getStyle('padding-right'), 10),
      parseInt(this.element.getStyle('border-left-width'), 10),
      parseInt(this.element.getStyle('border-right-width'), 10)
    ].sum();

    var vo = [
      parseInt(this.element.getStyle('margin-bottom'), 10),
      parseInt(this.element.getStyle('margin-top'), 10),
      parseInt(this.element.getStyle('padding-bottom'), 10),
      parseInt(this.element.getStyle('padding-top'), 10),
      parseInt(this.element.getStyle('border-bottom-width'), 10),
      parseInt(this.element.getStyle('border-top-width'), 10)
    ].sum();

    var h = this.options.height;
    var w = this.options.width;
    var t = Math.round((d.height-h)/2);
    var l = Math.round((d.width-w)/2);

    var style = {
      'height' : h-vo+'px',
      'left' : l+'px',
      'top' : t+'px',
      'width' : w-ho+'px'
    };

    this.style = style;

    this.element.setStyle(style);
    if(this.iframe){
      this.iframe.setStyle(Object.extend(style, {
        zIndex: 4999
      }));
    }
  },
  position : function(){

  },
  show : function(){
    this.resize();
    this._show();
  },
  hide : function(){
    this._hide();
  },
  _show : function(){
    this.element.show();
  },
  _hide : function(){
    this.element.hide();
  },
  update : function(content){
    this.content.stopObserving();
    this.content.descendants().invoke('stopObserving');
    this.content.update(content);
  }
});


dd.ui.Overlay.Mask = Class.create({
  initialize : function(options){
    this.options = Object.extend({
      'background' : '#000',
      'className' : 'dd-ui-overlay-mask',
      'opacity' : 0.5
    }, options||{});

    if(this.options.show && Object.isFunction(this.options.show)){
      this._show = this.options.show.bind(this);
    }

    if(this.options.hide && Object.isFunction(this.options.hide)){
      this._hide = this.options.hide.bind(this);
    }

    this.build();
  },
  build : function(){
    var style = {
      'left' : 0,
      'margin' : 0,
      'padding' : 0,
      'position' : 'absolute',
      'top' : 0,
      'width' : '100%',
      'zIndex' : 4000
    };

    this.element = new Element('div', {className : this.options.className}).setStyle(Object.extend({
      'background' : this.options.background,
      'opacity' : this.options.opacity,
      'overflow' : 'auto'
    }, style)).hide();

    document.body.appendChild(this.element);

    if(Prototype.Browser.IE6){
      this.iframe = new Element('iframe', {src: 'javascript:false'}).setStyle(Object.extend({
        'border' : 0,
        'opacity' : 0,
        'zIndex' : 3999
      }, style)).hide();

      document.body.appendChild(this.iframe);

      this.element.show = this.element.show.wrap(function(proceed){
        this.iframe.show();
        proceed();
      }.bind(this));

      this.element.hide = this.element.hide.wrap(function(proceed){
        proceed();
        this.iframe.hide();
      }.bind(this));
    }

    this.resize();
    Event.observe(window, 'resize', this.resize.bindAsEventListener(this));
  },
  resize : function(){
    var style = {
      'height' : Math.max(
        document.body.scrollHeight, document.documentElement.scrollHeight,
        document.body.offsetHeight, document.documentElement.offsetHeight,
        document.body.clientHeight, document.documentElement.clientHeight
      )+'px'
    };

    this.element.setStyle(style);
    if(this.iframe){
      this.iframe.setStyle(style);
    }
  },
  show : function(){
    this._show();
  },
  hide : function(){
    this._hide();
  },
  _show : function(){
    this.element.show();
  },
  _hide : function(){
    this.element.hide();
  }
});



dd.ui.Overlay.Modal = Class.create({
  initialize : function(options){
    if(!dd.ui.Overlay.Base || !dd.ui.Overlay.Mask){
      return false;
    }

    this.options = Object.extend({
    }, options||{});

    if(this.options.show && Object.isFunction(this.options.show)){
      this._show = this.options.show.bind(this);
    }

    if(this.options.hide && Object.isFunction(this.options.hide)){
      this._hide = this.options.hide.bind(this);
    }

    this.overlay = new dd.ui.Overlay.Base(this.options);

    this.closeButton = new Element('a', { 'class' : 'closeButton' } ).update('close'); 
    this.closeButton.observe('click', this.onClick.bindAsEventListener(this));
    
    this.overlay.element.insert({top : this.closeButton});
    
    this.mask = new dd.ui.Overlay.Mask();

    this.mask.element.observe('click', this.onClick.bindAsEventListener(this));
  },
  onClick : function(e){
    if(e.target == this.mask.element || e.target == this.closeButton){      
      e.stop();
      if(this.options.onClose){
        this.options.onClose();
      }else{
        this.hide();
      }
    }
  },
  show : function(){
    this._show();
  },
  hide : function(){
    this._hide();
  },
  _show : function(){
    this.mask.show();
    this.overlay.show();
  },
  _hide : function(){
    this.mask.hide();
    this.overlay.hide();
  },
  update : function(content){
    this.overlay.update(content);
  }
});

dd.ui.Overlay.AjaxModal = Class.create(dd.ui.Overlay.Modal, {
  initialize : function($super, options){
    var options = Object.extend({
    }, options||{});
    $super(options);
  },
  load : function(url, method){
    this.show();
    new Ajax.Request(url.uncache(), {
      method : method||'get',
      onSuccess : this.onLoad.bind(this)
    });
  },
  onLoad : function(t){
    if(!Object.isUndefined(pageTracker)){
      pageTracker._trackPageview(t.request.url.split('?')[0]);
    }
    var fx = new S2.FX.Morph(this.overlay.content, {
      'style' : 'opacity:1;',
      before : function(){
        this.overlay.content.setStyle({
          'opacity' : 0
        });
        this.update(t.responseText);
      }.bind(this),
      'position' : 'end'
    });
    fx.play();
  },
  reload : function(url, method){
    new Ajax.Request(url, {
      method : method||'get',
      onSuccess : function(t){
        this.overlay.update(t.responseText);
      }.bind(this)
    })
  }
});

dd.ui.Carousel = Class.create({
  initialize : function(element, options){
    this.element = $(element);
    this.options = Object.extend({
      duration : 0.2,
      items : 'li',
      size : 3,
      loop : true,
      step : 1,
      scroll : false,
      autoplay : false
    }, options||{});

    this.offset = 0;
    this.index = 0;
    this.build();
  },
  build : function(){
    this.items = this.element.select(this.options.items).invoke('remove');
    this.clipping = new Element('div', {className : 'dd-ui-carousel-clipping'});
    this.content = new Element('div', {className : 'dd-ui-carousel-content'});
    this.element.update(this.clipping.insert(this.content));
    this.width = this.content.getWidth()/this.options.size;

    $R(this.index, this.options.size-1).each(function(i){
      this.content.insert(this.items[i]);
    }, this);

    if(this.options.previous){
      this.element.insert(new Element('a', {className: 'dd-ui-carousel-control-previous', href: '#'}).update('Previous'));
    }

    if(this.options.next){
      this.element.insert(new Element('a', {className: 'dd-ui-carousel-control-next', href: '#'}).update('Next'));
    }

    this.element.observe('click', this.onClick.bindAsEventListener(this));

    if(this.options.autoplay){
      this.autoplay = new PeriodicalExecuter(this.next.bind(this), 2);
    }

  },
  onClick : function(e){
    if(e.findElement('a.dd-ui-carousel-control-previous')){
      e.stop();
      if(this.autoplay){
        this.autoplay.stop();
      }
      this.previous();
      return;
    }
    if(e.findElement('a.dd-ui-carousel-control-next')){
      e.stop();
      if(this.autoplay){
        this.autoplay.stop();
      }
      this.next();
      return;
    }
  },
  lock : function(){
    this.locked = false;
  },
  unlock : function(proceed){
    this.locked = false;
    proceed();
    if(this.options.onScroll){
      this.options.onScroll.call(this);
    }
    return;
  },
  tween : function(to, callback, speed){
    if(!this.locked){
      var fx = new S2.FX.HorizontalScroll(this.clipping, {
        to : this.get_offset(to),
        duration : speed||this.options.duration,
        after: callback.bind(this),
        before : this.lock.bind(this)
      });
      fx.play();
    }
  },
  next : function(i){
    var s = this.items.size();
    var from = this.index+this.options.size;
    from = (from > s-1) ? from-s : from;
    var to = (Object.isNumber(i)) ? i : from+this.options.step-1;
    $R(from, to).each(function(i){
      this.content.insert(this.items[((i>s-1) ? i=i-s : i)]);
    }, this);
    var step = to-from+1;    
    this.content.style.width = this.width*(this.options.size+step)+'px';
    this.clipping.scrollLeft = 0;
    this.tween(1, this.afterNext.curry(step), step*this.options.duration);
  },
  afterNext : function(step){
    $R(this.index, this.index+step-1).each(function(i){
      this.items[i].remove();
    }, this);
    this.clipping.scrollLeft = 0;    
    this.index += step;
    this.index = (this.index > this.items.size()-1) ? 0 : this.index;
  },
  previous : function(i){
    var s = this.items.size();
    var from = (Object.isNumber(i)) ? i : this.index-this.options.step;
    from = (from < 0) ? this.items.size()+from : from;
    var to = this.index-1;
    var step = to-from+1;
    var element = this.content.down();
    $R(from, to).each(function(i, n){
      element.insert({before: this.items[((i>s-1) ? i-s : i)]});
    }, this);    
    this.content.style.width = this.width*(this.options.size+step)+'px';
    this.clipping.scrollLeft = this.width*step;
    this.tween(0, this.afterPrevious.curry(step), step*this.options.duration);
  },
  afterPrevious : function(step){
    var s = this.index-step+this.options.size;
    var _s = this.items.size();
    $R(s, s+step-1).each(function(i){
      this.items[((i>_s-1) ? i-_s : i)].remove();
    }, this);
    this.clipping.scrollLeft = 0;
    this.index -= step;
    this.index = (this.index < 0) ? this.items.size()-step : this.index;
    
    //var item = this.items[this.index];
    //this.content.down(this.options.items).update(item.innerHTML);    
    //this.content.down(this.options.items).redraw();
    
  },
  get_offset : function(value){
    return Math.round(value/1 * (this.clipping.scrollWidth - this.clipping.offsetWidth));
  },
  scrollTo : function(i){
    var s = this.items.size();
    if(i<this.index){
      this.previous(i);
    }else if(i>this.index){
      this.next(i);
    }
  }
});

Element.addMethods({
  redraw: function(element){
    element = $(element);
    var n = document.createTextNode(' ');
    element.appendChild(n);
    (function(){n.parentNode.removeChild(n)}).defer();
    return element;
  }
});



S2.FX.Operators.HorizontalScroll = Class.create(S2.FX.Operators.Base, {
  initialize: function($super, effect, object, options) {
    $super(effect, object, options);
    this.start = object.scrollLeft;
    this.end = this.options.scrollTo;
  },
  valueAt: function(position) {
    return this.start + ((this.end - this.start)*position);
  },
  applyValue: function(value){
    this.object.scrollLeft = value.round();
  }
});

S2.FX.HorizontalScroll = Class.create(S2.FX.Element, {
  setup: function() {
    this.animate('HorizontalScroll', this.element, { scrollTo: this.options.to });
  }
});

dd.ui.Map = {};

dd.ui.Map.Base = Class.create({
  initialize : function(element, options){
    this.element = $(element);
    this.options = Object.extend({
      height : 400,
      width: 600,
      pan : false,
      zoom : false,
      map_type :  G_PHYSICAL_MAP,
      map_latitude : false,
      map_longitude : false
    }, options||{});

    this.geo = {};
    this.markers = $A();

    this.build();
    this.map = new GMap2(this.m);
    this.map.setMapType(this.options.map_type);

    if(!this.options.pan){
      this.map.disableDragging();
    }

    if(!this.options.zoom){
      this.map.disableDoubleClickZoom();
    }

    GEvent.addListener(this.map, "moveend", this.onMove.bind(this));
    GEvent.addListener(this.map, "zoomend", this.onZoom.bind(this));
    this.center();
  },
  enablePan : function(){
    this.map.enableDragging();
  },
  disablePan : function(){
    this.map.disableDragging();
  },
  enableZoom : function(){
    this.map.enableDoubleClickZoom();
  },
  disableZoom : function(){
    this.map.disableDoubleClickZoom();
  },
  build : function(){
    this.m = new Element('div', {className: 'map'}).setStyle({
      height : this.options.height+'px',
      width : this.options.width+'px'
    });
    this.element.insert(this.m);
  },
  center : function(){
    if(this.options.map_latitude && this.options.map_longitude && this.options.zoom){
      this.setCenter(this.getPoint(this.options.map_latitude, this.options.map_longitude), this.options.zoom);
    }else if(this.options.address){
      this.getLocation(this.options.address, this.options.id, function(point, zoom){
        this.setCenter(point, zoom);
        this.save();
      });
    }else if(navigator.geolocation){
    }
  },
  getLocation : function(address, id, callback){
    var c = callback.wrap(function(proceed, data){
      try{
        var bounds = this.getBoundsFromWOEID(data);
        var point = bounds.getCenter();
        var zoom = this.map.getBoundsZoomLevel(bounds);
        proceed(point, zoom);
      }catch(e){}
    });
    getJSON('http://where.yahooapis.com/v1/places.q(%27'+escape(address)+'%27)?format=json&appid=0hAohbDV34FSLcpx6KAOLgTzV28ZrEc57SP1IiD2phqfyv9hr_3LoBYQkMjLlOn3oXg-&callback=?', c.bind(this));
  },
  getBoundsFromWOEID : function(data){
    var place = data.places.place[0];
    var southWest = place.boundingBox.southWest;
    var northEast = place.boundingBox.northEast;
    var bounds = new GLatLngBounds(new GLatLng(southWest.latitude, southWest.longitude), new GLatLng(northEast.latitude, northEast.longitude));
    return bounds;
  },
  getPoint : function(latitude, longitude){
    return new GLatLng(latitude, longitude, true);
  },
  setCenter : function(point, zoom){
    this.map.setCenter(point, parseInt(zoom, 10));
    this.setMapLatLong(point);
    this.setZoom(zoom);
  },
  setMapLatLong : function(point){
    this.geo.map_lat = point.y;
    this.geo.map_long = point.x;
  },
  setZoom : function(zoom){
    this.geo.zoom = this.map.getZoom();
  },
  onMove : function(){
    this.setMapLatLong(this.map.getCenter());
  },
  onZoom : function(){
    this.setZoom();
  },
  addMarker : function(options){
    var marker = new dd.ui.Map.Marker(this.map, options);
    this.markers.push(marker);
    if(options.latitude && options.longitude){
      marker.plot(this.getPoint(options.latitude, options.longitude));
    }else if(options.address){
      this.getLocation(options.address, options.id, function(point, z){
        marker.plot(point);
      });
    }
    return marker;
  },
  addPath : function(points, options){
    var p = $A();
    var path = new dd.ui.Map.path(this.map, options);
    var size = points.size();
    points.each(function(point, i){
      point.first = i==0;
      point.last = i==size-1;
      point.order = i;
      point.status = this.status;
      if(point.latitude && point.longitude){
        point.point = this.getPoint(point.latitude, point.longitude);
        p.push(point);
      }else if(point.address){
        this.getLocation(options.address, options.id, function(_p, z){
          point.point = _p;
          p.push(point);
          if(p.size()==size){
            path.plot(p);
          }
        });
      }
    }, this);
    if(p.size()==size){
      path.plot(p);
    }
    return path;
  },
  fitMapToMarkers : function(e){
    if(e) e.stop();
    if(this.markers){
      var polyline = new GPolyline(this.markers.pluck('point'), "#FF0000", 10);
      var bounds = polyline.getBounds();
      this.setCenter(bounds.getCenter(), this.map.getBoundsZoomLevel(bounds));
    }
  }
});

dd.ui.Map.Icon = Class.create({
  initialize : function(icon, options){
    this.options = Object.extend({
    }, options);
    this.options = Object.extend({
      anchorLeft : (this.options.width/2),
      anchorTop : (this.options.height/2),
      windowLeft : (this.options.width/2),
      windowTop : (this.options.height/2),
      imageMap : [0,0,this.options.width,0,this.options.width,this.options.height,0,this.options.height]
    }, this.options)

    this.icon = new GIcon(G_DEFAULT_ICON);
    this.icon.image = icon;
    this.icon.iconSize = new GSize(this.options.width, this.options.height);
    this.icon.iconAnchor = new GPoint(this.options.anchorLeft, this.options.anchorTop);
    this.icon.infoWindowAnchor = new GPoint(this.options.windowLeft, this.options.windowTop);
    this.icon.imageMap = this.options.imageMap;
  }
});

dd.ui.Map.Marker = Class.create({
  initialize : function(map, options){
    this.map = map;
    this.options = Object.extend({
      draggable : false,
      onDrag : Prototype.emptyFunction,
      labelClassName : 'ui-map-label'
    }, options||{});

    this.markerOptions = {
      draggable : this.options.draggable
    };

    if(this.options.label){
      this.label = new Element('div').setStyle({
        'position' : 'absolute'
      }).update(new Element('div', {'className' : this.options.labelClassName}).update(this.options.label));
    }


    if(this.options.icon && this.options.icon.icon){
      this.markerOptions.icon = this.options.icon.icon;
    }

    if(this.label){
      this.map.getPane(G_MAP_MARKER_PANE).appendChild(this.label);
    }

  },
  plot : function(point){
    this.point = point;
    if(!this.marker){
      this.marker = new GMarker(point, this.markerOptions);
      this.map.addOverlay(this.marker);
      
      var html = '<p style="margin-bottom:10px;color:#333;"><strong>Find your way to Five by Five</strong></p><p style="color:#333;">Start address:<form action="http://maps.google.com/maps" method="get"><input type="text" size="30" name="saddr" id="saddr" value="" style="width:150px;"/> ' +
      '<input value="Go" type="submit"></p>' +
      '<input type="hidden" name="daddr" value="' + point.lat() + ',' + point.lng() +' />';      
      
      GEvent.addListener(this.marker, "click", function() {
         this.marker.openInfoWindowHtml(html);
      }.bind(this));
    }else{
      this.marker.setLatLng(point)
    }

    if(this.label){
      var position = this.map.fromLatLngToDivPixel(this.point);
      var dimensions = this.label.getDimensions();
      var m = this.marker.getIcon().iconSize;
      var a = this.marker.getIcon().iconAnchor;

      this.label.setStyle({
        'left' : position.x+(m.width/2)+'px',
        'top' : position.y-(m.height/2)-(dimensions.height/2)+a.y+'px'
      });
    }

  },
  update : function(options){
    this.plot(new GLatLng(options.latitude, options.longitude, true));
  }
});

dd.ui.Map.Path = Class.create({
  initialize : function(map, options){
    this.map = map;
    this.options = Object.extend({
      'color' : '#ff0000',
      'width' : 2
    }, options||{});
  },
  plot : function(points){
    this.points = points.sortBy(function(point){
      return point.order;
    });
    if(!this.path){
      this.path = new GPolyline(this.points.pluck('point'), this.options.color, this.options.width);
      this.map.addOverlay(this.path);
    }else{
      this.map.removeOverlay(this.path);
      this.path = new GPolyline(this.points.pluck('point'), this.options.color, this.options.width);
      this.map.addOverlay(this.path);
    }
  },
  push : function(options){
    var point = new GLatLng(options.latitude, options.longitude, true);
    var size = this.points.size();
    var last = this.points.last();
    if(size==0 || (last.options.latitude != options.latitude && last.longitude != options.longitude)){
      this.points.last().options.last = false;
      this.points.push({
        order: size,
        point : point,
        last : true
      });
      this.plot(this.points);
    }
  }
});

dd.ui.Slideshow = Class.create({
  initialize : function(element, options){
    if(!(this.element=$(element))) return;
    this.options = Object.extend({
      item : 'li'
    }, options||{});
    this.index = 0;
    this.build();
    this.play();
  },
  build : function(){
    this.slides = [];
    this.element.select(this.options.item).each(function(item, i){
      var options = {};
      var img = item.down('img');
      options.src = img.src;
      if(img.title){
        options.caption = img.title;
      }
      var link = item.down('a');
      if(link){
        options.url = link.href;
      }
      this.slides.push(options);
      item.hide();
    }, this);
    this.size = this.slides.length;
    this.wrapper = new Element('div').setStyle({
      'position' : 'relative'
    });
    this.nextImg = new Element('img').setStyle({
      'display' :  'block',
      'height' : '100%',
      'width' : '100%',
      'top' : 0,
      'left' : 0,
      'position' : 'absolute'
    }).hide();
    this.img = new Element('img', {src: this.slides[0].src}).setStyle({
      'display' : 'block'
    });
    this.caption = new Element('div', {className:'caption'}).setStyle({
      'display' :  'block',
      'height' : '100%',
      'width' : '100%',
      'top' : 0,
      'left' : 0,
      'position' : 'absolute'
    }).update('<div>'+this.slides[0].caption+'</div>');
    this.nextCaption = new Element('div', {className:'caption'}).setStyle({
      'display' :  'block',
      'height' : '100%',
      'width' : '100%',
      'top' : 0,
      'left' : 0,
      'position' : 'absolute'
    });
    this.wrapper.insert(this.img);
    this.wrapper.insert(this.nextImg);
    this.wrapper.insert(this.caption);
    this.wrapper.insert(this.nextCaption);
    this.element.insert(this.wrapper);
  },
  play : function(){
    this.p = new PeriodicalExecuter(this.next.bind(this), 5);
  },
  pause : function(){

  },
  next : function(){
    this.index++;
    this.transition(this.slides[this.index]);
    if(this.index==this.size-1){
      this.index = -1;
    }
  },
  previous : function(){

  },
  transition : function(slide){
    this.nextImg.src = slide.src;
    this.nextImg.setStyle({
      'opacity' : 0
    }).show();
    this.nextCaption.setStyle({
      'top' : '-600px'
    }).show().update('<div>'+slide.caption+'</div>');

    var fx = new S2.FX.Parallel([
      new S2.FX.Morph(this.nextImg, {
        'style' : 'opacity:1;'
      }),
      new S2.FX.Morph(this.caption, {
        'style' : 'left:800px;'
      }),
      new S2.FX.Morph(this.nextCaption, {
        'style' : 'top:0;'
      })
    ], {
      duration : 1,
      after : function(){
        this.img.src = this.nextImg.src;
        this.nextImg.hide();
        this.caption.update(this.nextCaption.innerHTML).setStyle({
          'left' : 0
        });
        this.nextCaption.hide();
      }.bind(this)
    });
    fx.play();
  }
});

$E = Event[(Object.isFunction(Event.register)) ? 'register' : 'observe'];

(function(){
  var id = 0, head = $$('head')[0], global = this;
  global.getJSON = function(url, callback) {
    var script = document.createElement('script'), token = '__jsonp' + id;
    global[token] = callback;
    script.src = url.replace(/\?(&|$)/, '__jsonp' + id + '$1');
    script.onload = function() {
      script.remove();
      script = null;
      delete global[token];
    };
    head.appendChild(script);
    id++;
  }
})();
