var DropShadow = Class.create();
DropShadow.prototype = {
  pieces: [
    { x: -9, y: -9, w: 27, h: 20, ele: 'shadow_top_left', is_right: false, is_bottom: false },
    { x: 18, y: -2, w: -21, h: 2, ele: 'shadow_top', is_right: false, is_bottom: false },
  	{ x: -3, y: -2, w: 8, h: 8, ele: 'shadow_top_right', is_right: true, is_bottom: false },
  	{ x: -3, y: 11, w: 3, h: -13, ele: 'shadow_left', is_right: false, is_bottom: false },
  	{ x: 0, y: 6, w: 5, h: -8, ele: 'shadow_right', is_right: true, is_bottom: false },
  	{ x: -3, y: -2, w: 8, h: 8, ele: 'shadow_bottom_left', is_right: false, is_bottom: true },
  	{ x: 5, y: 0, w: -8, h: 6, ele: 'shadow_bottom', is_right: false, is_bottom: true },
  	{ x: -3, y: -2, w: 8, h: 8, ele: 'shadow_bottom_right', is_right: true, is_bottom: true }
  ],
  minX: -9,
  minY: -9,
  maxX: 5,
  maxY: 6,
 	initialize: function(id, border){
    this.obj = $(id);
    this.objBorderWidth = border;
  },
  drawPiece: function(pos) {
    var d = { }
    $(pos.ele).style.display = "block"; // to combat strange bug with trying to show these things after positioning
    Position.clone(this.obj, pos.ele);
    $(pos.ele).style.left = pos.x+this.objBorderWidth+((pos.is_right) ? this.obj.offsetWidth : 0)+$(pos.ele).offsetLeft + 'px';
    $(pos.ele).style.top = pos.y+this.objBorderWidth+((pos.is_bottom) ? this.obj.offsetHeight : 0)+$(pos.ele).offsetTop + 'px';
    $(pos.ele).style.width = ((pos.w > 0) ? pos.w : this.obj.offsetWidth + pos.w) + 'px';
    $(pos.ele).style.height = ((pos.h > 0) ? pos.h : this.obj.offsetHeight + pos.h) + 'px';
  },
  draw: function() {
    for(var i=0; i<this.pieces.length; i++) {
      this.drawPiece(this.pieces[i]);
    }
  },
  erase: function() {
    for(var i=0; i<this.pieces.length; i++) {
      Element.hide(this.pieces[i].ele);
    }
  }
}

var MapRegion = Class.create();
MapRegion.prototype = {
  initialize: function(ele, z) {
    var sub = 'o_eco_map_dd_'+z+'_';
    this.node = ele;
    this.link = ele.innerHTML;
    this.name = ele.id.substring(sub.length);
    var links = ele.getElementsByTagName('a');
    if (links.length > 0) this.text = links[0].innerHTML;
    this.dt = 'oeco_location_dt_'+z+'_'+this.name;
    this.dd = 'oeco_location_dd_'+z+'_'+this.name;
  },
  switchOn: function() {
    this.node.innerHTML = this.text;
    $(this.dt).style.display = "block";
    $(this.dd).style.display = "block";
  },
  switchOff: function() {
    this.node.innerHTML = this.link;
    $(this.dt).style.display = "none";
    $(this.dd).style.display = "none";
  }
}
var MapZone = Class.create();
MapZone.prototype = {
  visible: false,
  hover: false,
  locked: false,
  initialize: function(z) {
    this.name = z;
    this.marker = "o_eco_map_dt_"+z;
    this.marker_link = "o_eco_map_a_"+z;
    this.region_pop = "o_eco_map_dd_"+z;
    this.regions = new Array();
    var node_regions = $(this.region_pop).getElementsByTagName('li');
    for(var i=0; i<node_regions.length; i++) {
      this.regions.push(new MapRegion(node_regions[i], this.name));
    }
    this.ds = new DropShadow('o_eco_map_dd_'+z, 1);
    $(this.marker_link).onclick = this.lock.bindAsEventListener(this);
    $(this.marker_link).onmouseover = this.mouseOverZone.bindAsEventListener(this);
    $(this.marker_link).onmouseout = this.mouseOutZone.bindAsEventListener(this);
    this.my_track = this.track.bindAsEventListener(this);
    this.my_freeze = this.freeze.bindAsEventListener(this);
  },
  show: function() {
    if (!this.visible) {
      estateMap.hideAllZonesExcept(this.name);
      if (this.locked) Element.addClassName(this.marker, 'on');
      Element.addClassName(this.region_pop, 'on');
      this.ds.draw();
      this.visible = true;
      var pos = Position.cumulativeOffset($(this.region_pop));
      this.bounds = {
        min_x: pos[0] + this.ds.minX,
        min_y: pos[1] + this.ds.minY,
        max_x: pos[0] + $(this.region_pop).offsetWidth + this.ds.maxX,
        max_y: pos[1] + $(this.region_pop).offsetHeight + this.ds.maxY
      }
      Event.observe(document, 'mousemove', this.my_track, false);
      Event.observe(document, 'click', this.my_freeze, false);
      if (typeof(this.onShow)!="undefined") this.onShow();
    }
  },
  hide: function(forced) {
    if (!this.locked || forced) {
//      if (this.locked) Element.removeClassName(this.marker, 'on');
      Element.removeClassName(this.region_pop, 'on');
      this.ds.erase();
      this.visible = false;
      this.hoverZone = false;
      Event.stopObserving(document, 'mousemove', this.my_track, false);
      Event.stopObserving(document, 'click', this.my_freeze, false);
      if (typeof(this.onHide)!="undefined") this.onHide();
    }
  },
  track: function(evt) {
    if (this.hover || this.isInBounds(evt)) this.show();
    else {
      this.hide();
      estateMap.restoreLocked();
    }
  },
  freeze: function(evt) {
    //see if the click is even on the map
    var my_x = Event.pointerX(evt);
    var my_y = Event.pointerY(evt);
    if (my_x < estateMap.mapMinX || my_y < estateMap.mapMinY || my_x > estateMap.mapMaxX || my_y > estateMap.mapMaxY) return;
    if (this.hover || this.isInBounds(evt)) {
      this.lock(evt);
    } else {
      this.unlock(evt);
    }
  },
  isInBounds: function(evt) {
    var my_x = Event.pointerX(evt);
    var my_y = Event.pointerY(evt);
    return ((my_x >= this.bounds.min_x) && (my_x < this.bounds.max_x) && (my_y >= this.bounds.min_y) && (my_y < this.bounds.max_y));
  },
  lock: function(evt) {
    estateMap.removeAllLocksExcept(this.name);
    this.locked = true;
    $(this.marker_link).onclick = this.unlock.bindAsEventListener(this);
    Element.addClassName(this.marker, 'on');
    return false;
  },
  unlock: function(evt) {
    this.locked = false;
    $(this.marker_link).onclick = this.lock.bindAsEventListener(this);
    Element.removeClassName(this.marker, 'on');
    this.regions.each(function(region) {
        region.switchOff();
      });
    return false;
  },
  mouseOverZone: function(evt) {
    this.hover = true;
    this.show();
  },
  mouseOutZone: function(evt) {
    this.hover = false;
  }
}
var EstateMapper = Class.create();
EstateMapper.prototype = {
  zones: { },
  initialize: function() { },
  addZone: function(z) {
    if (!this.gotCoords) {
      var map_coords = Position.cumulativeOffset($('o_eco_map'));
      this.mapMinX = map_coords[0];
      this.mapMinY = map_coords[1];
      var map_dims = Element.getDimensions($('o_eco_map'));
      this.mapMaxX = map_coords[0] + map_dims.width;
      this.mapMaxY = map_coords[1] + map_dims.height;
      this.gotCoords = true;
    }
    eval("this.zones." + z + " = new MapZone('" + z + "');");
  },
  hideAllZonesExcept: function(z) {
    for(var i in this.zones) {
      if (this.zones[i].name != z) {
        if (Element.hasClassName(this.zones[i].region_pop, 'on')) {
          this.zones[i].visible = true;
          this.zones[i].hide(true);
        }
      }
    }
  },
  removeAllLocksExcept: function(z) {
    for(var i in this.zones) {
      if (this.zones[i].name != z && this.zones[i].locked) {
        this.zones[i].unlock("");
      }
    }
  },
  restoreLocked: function() {
    for(var i in this.zones) {
      if (this.zones[i].locked) {
        this.zones[i].show();
      }
    }
  },
  showRegion: function(r, z) {
    var zone = eval("this.zones." + z);
    zone.regions.each(function(region) {
        (r == region.name) ? region.switchOn() : region.switchOff();
      });
    zone.lock();
  },
  getZoneIdFromDraggable: function(e) {
    return e.id.substring(16);
  },
  initDrag: function(e) {
    var id = this.getZoneIdFromDraggable(e);
    var z = eval("this.zones." + id);
    if (z.visible) z.ds.erase();
  },
  endDrag: function(e) {
    var id = this.getZoneIdFromDraggable(e);
    var z = eval("this.zones." + id);
    if (z.visible) z.ds.draw();
  }
}
var estateMap = new EstateMapper();

var LargeSlideshow = Class.create();
LargeSlideshow.prototype = {
  ids: [],
  images: [],
  htmls: [],
  paused: true,
  timeout_id: 0,
  index: 0,
  initialize: function(prefix) {
    this.prefix = prefix;
  },
  add: function(id, image, html) {
    this.ids.push(id);
    this.images.push(image);
    this.htmls.push(html);
  },
  slide: function() {
    var old_dt = this.prefix + "dt_" + this.ids[this.index];
    var old_dd = this.prefix + "dd_" + this.ids[this.index];
    this.index = ( this.index + this.ids.length + 1 ) % this.ids.length;
    var new_dt = this.prefix + "dt_" + this.ids[this.index];
    var new_dd = this.prefix + "dd_" + this.ids[this.index];
    Effect.Fade(old_dt, {duration:2.0});
    Effect.Fade(old_dd, {duration:2.0});
    Effect.Appear(new_dt, {duration:2.0});
    Effect.Appear(new_dd, {duration:2.0});
    if (!this.paused) {
      this.timeout_id = setTimeout(this.slide.bind(this), 5000);
    }
  },
  begin: function() {
    for(var i=0; i<document.images.length; i++) {
      if (document.images[i].complete === false) {
        setTimeout(this.begin.bind(this), 500);
        return;
      }
    }
    if (this.paused) {
      this.paused = false;
      setTimeout(this.begin.bind(this), 200);
      return;
    }
    for(var i=1; i<this.images.length; i++) {
      var img = new Image();
      img.src = this.images[i];
      if (i>0) { new Insertion.Bottom('large_slide_image_dl', this.htmls[i]); }
    }
    this.timeout_id = setTimeout(this.slide.bind(this), 3000);
  }
}

var Slideshow = Class.create();
Slideshow.prototype = {
  thumbs: [],
  images: [],
  paused: false,
  timeout_id: 0,
  last_index: -1,
  initialize: function(prefix, controls, container, name) {
    this.prefix = prefix;
    this.controls = controls;
    this.container = container;
    this.name = name;
  },
  add: function(thumb, image) {
    var img = new Image();
    img.src = thumb;
    this.thumbs.push(thumb);
    this.images.push(image);
  },
  setup: function() {
    $(this.container).style.height = Element.getHeight($(this.container)) + "px";
    this.length = this.images.length;
    for (var i=0; i<this.length; i++) {
      $(this.prefix + i).style.position = 'absolute';
      Position.clone(this.container, this.prefix + i);
    }
    var html = '<li id="prev"><a href="#" onclick="' + this.name + '.slide(-1);return false;">Previous</a></li><li id="pause"><a href="#" onclick="' + this.name + '.pause();return false;">Pause</a></li><li id="next"><a href="#" onclick="' + this.name + '.slide(1);return false;">Next</a></li>';
    this.index = 0;
    new Insertion.Top(this.controls, html);
    this.timeout_id = setTimeout(this.advance.bind(this), 5000);
  },
  slide: function(dir) {
    if (this.paused && this.timeout_id != 0) {
      clearTimeout(this.timeout_id);
      this.timeout_id = 0;
    } else {
      if (this.last_index >= 0) {
        this.last_fade.cancel();
        this.last_appear.cancel();
        Element.hide(this.prefix + this.last_index);
      }
      this.last_index = this.index;
      var old_d = this.prefix + this.index;
      this.index = ( this.index + this.images.length + 1 ) % this.images.length;
      var new_d = this.prefix + this.index;
      this.last_fade = Effect.Fade(old_d);
      this.last_appear = Effect.Appear(new_d);
      if (this.timeout_id != 0) {
        clearTimeout(this.timeout_id);
        this.timeout_id = 0;
      }
      if (!this.paused) this.timeout_id = setTimeout(this.advance.bind(this), 5000);
    }
  },
  pause: function() {
    Element.addClassName("pause", "play");
    $("pause").innerHTML = '<a href="#" onclick="' + this.name + '.play();return false;">Play</a>';
    this.paused = true; 
    clearTimeout(this.timeout_id);
    this.timeout_id = 0;
  },
  play: function() {
    Element.removeClassName("pause", "play");
    $("pause").innerHTML = '<a href="#" onclick="' + this.name + '.pause();return false;">Pause</a>';
    this.paused = false;
    this.slide(1);
  },
  advance: function() {
    this.timeout_id = 0
    this.slide(1);
  }
}

var creditLeftPos = 0;
var creditTopPos = 0;

function showCredits() {
  // not sure why this is necessary...  prototype is a bit buggy.
  Element.setOpacity('credits', 0.0);
  $('credits').style.display = 'block';
  if (creditLeftPos == 0) {
    Position.clone('credits_popper', 'credits');
    creditLeftPos = ($('credits').offsetLeft-225) + "px";
    creditTopPos = ($('credits').offsetTop-64) + "px";
    $('credits').style.left = creditLeftPos;
    $('credits').style.top = creditTopPos;
  }
  Effect.Appear('credits', {duration:0.5});
}
function hideCredits() {
  Effect.Fade('credits', {from:1.0, to:0.0, duration:0.5});
}
