var dd = {};

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

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().pad(2); break;
        case 'H': return hours.pad(2); break;
        case 'i': return (hours === 12 || hours === 0) ? 12 : (hours + 12) % 12; break;
        case 'I': return ((hours === 12 || hours === 0) ? 12 : (hours + 12) % 12).pad(2); break;
        case 'm': return (month + 1).pad(2); break;
        case 'M': return minutes.pad(2); break;
        case 'p': return hours > 11 ? 'PM' : 'AM'; break;
        case 'S': return this.getSeconds().pad(2); break;
        case 'w': return this.getWeek(); break;
        case 'y': return (this.getFullYear() % 100).pad(2); 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 mousedown');
  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);
    });
  }

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

dd.ui = {};

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,
      pan_control : false,
      zoom : false,
      zoom_control : false,
      map_type :  G_PHYSICAL_MAP,
      map_latitude : false,
      map_longitude : false,
      map_zoom: 15
    }, 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();
    }
    
    if(this.options.pan_control && this.options.zoom_control){
      this.map.addControl(new GLargeMapControl());
    }

    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.map_zoom){
      this.setCenter(this.getPoint(this.options.map_latitude, this.options.map_longitude), this.options.map_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));
      this.map.getPane(G_MAP_MARKER_PANE).appendChild(this.label);
      
    }


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



  },
  plot : function(point){
    this.point = point;
    if(!this.marker){
      this.marker = new GMarker(point, this.markerOptions);
      this.map.addOverlay(this.marker);
      // GEvent.addListener(this.marker, "click", function() {
      //    this.marker.openInfoWindowHtml('<p>Hello</p>');
      // }.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 = '<span class="t">'+img.title+'</span>';
      }
      if(img.getAttribute('longdesc')){
        options.caption += '<span class="l">'+img.getAttribute('longdesc')+'</span>';
      }
      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',
      'height' : '383px',
      'width' : '734px'
    });
    this.nextImg = new Element('img').setStyle({
      'display' :  'block',
      'height' : '100%',
      'width' : '100%',
      'top' : 0,
      'left' : 0,
      'position' : 'absolute',
      'zIndex' : 2
    }).hide();
    this.img = new Element('img', {src: this.slides[0].src}).setStyle({
      'display' : 'block',
      'zIndex' : 1
    });
    this.caption = new Element('div', {className:'caption'}).setStyle({
      'display' :  'block',
      'height' : '100%',
      'width' : '100%',
      'top' : 0,
      'left' : 0,
      'position' : 'absolute',
      'zIndex' : 3
    }).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',
      'zIndex' : 4
    });
    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);
    this.element.observe('click', this.onClick.bindAsEventListener(this));
  },
  onClick : function(e){
    e.stop();
    var link = this.slides[this.index].url;
    if(link){
      document.location=link;
    }
  },
  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' : '-343px'
    }).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' : 'top:343px;'
      }),
      new s2.fx.Morph(this.nextCaption, {
        'style' : 'top:0;'
      })
    ], {
      duration : 0.5,
      after : function(){
        this.img.src = this.nextImg.src;
        this.nextImg.hide();
        this.caption.update(this.nextCaption.innerHTML).setStyle({
          'top' : 0
        });
        this.nextCaption.hide();
      }.bind(this)
    });
    fx.play();
  }
});

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