function CanvasFF30Compat(proto){
  if(document.all){
    return;
  }
  if(proto.mozMeasureText && !proto.measureText) {
    proto.__defineSetter__('font', function(x) { this.mozTextStyle = x;});
    proto.__defineGetter__('font', function() { return this.mozTextStyle;});
  }
  if(proto.mozMeasureText && !proto.measureText) {
    proto.measureText = function(text) { return {'width': this.mozMeasureText(text)}; };
  }
  if(proto.mozPathText && !proto.strokeText) {
    proto.strokeText = function(text, x, y) {
      this.translate(x, y);
      this.mozPathText(text);
      this.stroke();
      this.translate(-x, -y);
    };
  }
  if(proto.mozDrawText && !proto.fillText) {
    proto.fillText = function(text, x, y) {
      this.translate(x, y);
      this.mozDrawText(text);
      this.translate(-x, -y);
    };
  }
}

  function initImage(src){
	  var i = new Image();
          var udf;
          if(window.loadedImages != udf)
            window.loadedImages[src] = i;	  
	  i.src = src;
	  return i;
  }
function MapInit(){
    window.loadedImages = {};
  
  var contextEl = document.getElementById("mapCanvas");
  var jContextEl = $(contextEl);
  var width = parseInt(contextEl.width);
  var height = parseInt(contextEl.height);
  var listItem = $("#squadlist ul");
  if(listItem[0].nodeName.toUpperCase() != "UL"){
	  listItem = null;
  } else {
	  listItem.css("width", width.toString() + "px");
  }    
  var context = contextEl.getContext("2d");
  context.lineWidth = 1;
  CanvasFF30Compat(context);    
  var fps = (document.all) ? 10 : 30;
  var framerate = 1000 / fps;
  var lastUpdate = null;
  var mapBg = initImage("images/map/Map.jpg");
  var meridiemMask = (document.all) ? null : initImage("images/map/MeridiemMask.png");
  var kDefaultFont = "8pt Arial,Helvetica,sans-serif";
  var kDefaultAlpha = 0.3;
  var kHoveringAlpha = 0.7;
  var infoBackgroundColor = [100, 100, 100];
  var tourIsRunning = false;
  var timeToWaitForTour = 15000;
  var idleTime = 0;
  var scanLinePassTime = 2000;
  var scanLineWaitTime = 5000;
  var scanLineWaited = 0;
  var scanLineAlpha = 0.11;
  var meridiemOffset = 0;
  

  function pointInRect(px, py, rx, ry, rw, rh){
	  var ul = [rx, ry];
	  var lr = [rx + rw, ry + rh];
	  return (px >= ul[0] && px <= lr[0]) && (py >= ul[1] && py <= lr[1]);
  };
  function drawImageWithAlpha(context, image, dx, dy, dw, dh, alpha){
    var img;
	  if(image != img){
	    var pAlpha = context.globalAlpha;
	    context.globalAlpha = alpha;
	    try {
		context.drawImage(image, dx, dy, dw, dh);
	    } catch(err){
	    }
	    context.globalAlpha = pAlpha;
	  }
  };
  function triggerEventIfDifferent(previous, newvalue, event, target){
	  if(previous != newvalue){
	    $(target).trigger(event);
	  }
  }
  function triggerOneOfPairIsTrue(previous, newvalue, eventIfTrue, eventIfFalse, target){
	  if(newvalue != previous){
	    if(newvalue)
		    triggerEventIfDifferent(previous, newvalue, eventIfTrue, target);
	    else
		    triggerEventIfDifferent(previous, newvalue, eventIfFalse, target);
	  }
  }
  function drawTextWithFontAndStyle(context, font, style, text, x, y, mw){
	  context.font = font;
	  context.fillStyle = style;
	  context.fillText(text, x, y);
  };
  var Drawable = function(dx, dy, dw, dh, src, drawFunc){
	  this.x = dx;
	  this.y = dy;
	  this.width = dw;
	  this.height = dh;
	  this.visible = false;
	  this.alpha = 1.0;
	  this.image = initImage(src);
	  this.focusedFaction = null;
	  this.centeredFactionCoords = function(f){
	    var cx = f.x + f.width / 2;
	    var cy = f.y + f.height / 2;
	    var hw = this.width / 2;
	    var hh = this.height / 2;
	    return [cx-hw, cy-hh];
	  };
	  this.centerOnFaction = function(f){
	    var coords = this.centeredFactionCoords(f);
	    this.focusedFaction = f;
	    this.x = coords[0];
	    this.y = coords[1];
	  };
	  this.moveToFaction = function(f){
	    var coords = this.centeredFactionCoords(f);
	    this.focusedFaction = f;
	    $(this).animate({
		                    x : coords[0],
		                    y : coords[1]
		                  }, 250, "easeInOutCirc");
	  };
	  this.fadeIn = function(){
	    $(this).stop();
	    this.alpha = 0.0;
	    this.visible = true;
	    $(this).animate({
		                    alpha : "1.0"
	                    }, 500, "easeInCirc");
	  };
	  this.fadeOut = function(){
	    $(this).stop();
	    this.alpha = 1.0;
	    this.visible = true;
	    $(this).animate({
		                    alpha : "0.0"
	                    }, 500, "easeOutCirc", function(){
		                    this.visible = false;
	                    });	    
	  };
	  this.draw = function(context, w, h){
	    drawImageWithAlpha(context, this.image, this.x, this.y, this.width, this.height, this.alpha);
	  };
  };
  var scanline = new Drawable(width, 0, 80, height, "images/map/gradient-scanline.png");
  scanline.alpha = scanLineAlpha;
  scanline.draw = function(context, w, h){
	  drawImageWithAlpha(context, this.image, this.x, this.y, this.width, this.height, this.alpha);	
  };
  var crosshair = new Drawable(0, 0, 99, 99, "images/map/circle.png");
  crosshair.draw = function(context, w, h){
	  drawImageWithAlpha(context, this.image, this.x, this.y, this.width, this.height, this.alpha);	    
	  var hh = this.y + this.height / 2;
	  var opp = this.x + this.width;
	  var rem = w - opp;
	  context.beginPath();
	  context.moveTo(this.x - (this.x * this.alpha), hh);
	  context.lineTo(this.x, hh);
	  context.moveTo(opp, hh);
	  context.lineTo(opp + (rem * this.alpha), hh);
	  context.closePath();
	  context.strokeStyle = "rgba(255,255,255," + this.alpha + ")";	    
	  context.stroke();
	  if(this.focusedFaction){
	      var infoOffset = 10;
	      var infoWidth = this.focusedFaction.dialog.width;
	    var sx = (opp + infoWidth + infoOffset) > w ? this.x - (infoWidth + infoOffset) : opp + infoOffset;
	    drawImageWithAlpha(context, this.focusedFaction.dialog, sx, hh, this.focusedFaction.dialog.width, this.focusedFaction.dialog.height, this.alpha);

	  }
  };
  var Faction = function(name, dx, dy, dw, dh, img, small_logo, large_logo, blade, dialog, megacon, region, status, squadname, squadhref, squad_images){
	  this.name = name;
	  this.x = dx;
	  this.y = dy;
	  this.width = dw;
	  this.height = dh;
	  this.image = initImage(img);
	  this.small_logo = initImage(small_logo);
	  this.large_logo = initImage(large_logo);
	  this.blade = initImage(blade);
	  this.dialog = initImage(dialog);
	  this.megacon = megacon;
	  this.region = region;
	  this.status = status;
	  this.squadname = squadname;
	  this.squadhref = squadhref;
	  this.squad_images = [];
	  for(var i = 0; i < squad_images.length; i ++){
	    this.squad_images.push({
		                           href : squad_images[i].href,
		                           image : initImage(squad_images[i].src),
		                           alt : squad_images[i].alt
	                           });
	  }
	  this.alpha = kDefaultAlpha;
	  this.selected = false;
	  this.hovering = false;
	  this.visible = true;
	  this.setHovering = function(b){
	    var previous = this.hovering;
	    this.hovering = b;
	    triggerOneOfPairIsTrue(previous, b, "didBecomeHovering", "didStopHovering", this);
	  };
	  this.setSelected = function(b){
	    var previous = this.selected;
	    this.selected = b;
	    triggerOneOfPairIsTrue(previous, b, "didBecomeSelected", "didStopBeingSelected", this);
	    if(this.selected){
		    // less than optimal, but good enough atm
		    for(var k in Faction.all){
		      var f = Faction.all[k];
		      if(f.selected && f != this){
			      f.setSelected(false);
		      }
		    }
	    }
	  };
	  this.setVisible = function(b){
	    var previous = this.visible;
	    this.visible = b;
	    triggerOneOfPairIsTrue(previous, b, "didBecomeVisible", "didStopBeingVisible", this);	    
	  };
	  Faction.all[name] = this;
          this.index = Faction.list.length;
          Faction.list.push(this);
  };
  Faction.list = [];
  Faction.all = {};

  var udf;
  if(window["factions"] != udf && window["factions"] != null){
	  for(var nm in factions){
	    var h = factions[nm];
	    var f = new Faction(nm, h["dx"], h["dy"], h["dw"], h["dh"], h["src"], h["small_logo"], h["large_logo"], h["blade"], h["dialog"], h["megacon"], h["region"], h["status"], h["squadname"], h["squadhref"], h["squad_images"]);
	    $(f).bind("didBecomeSelected", function(){
		              this.alpha = 1.0;
		              this.setVisible(true);
                  if(!tourIsRunning){
		                if(!crosshair.visible){
		                  crosshair.centerOnFaction(this);
		                  crosshair.fadeIn();
		                } else {
		                  crosshair.moveToFaction(this);
		                }                    
                  }

		  listItem.html("<li class='info'><a href='" + this.squadhref + "'><img border='0' src='" + this.blade.src + "'/></a></li>");
		              for(var i = 0; i < this.squad_images.length; i++){
		                listItem.append("<li><a href='" + this.squadhref + "'><img src='" + this.squad_images[i].image.src + "' alt='" + this.squad_images[i].alt + "' border='0'/></a></li>");
		              }
	              });
	    $(f).bind("didStopBeingSelected", function(){
		              if(!this.hovering){
		                this.alpha = kDefaultAlpha;
		              } else {
		                crosshair.fadeOut();
		              }
	              });
	    $(f).bind("didStopHovering", function(){
		              if(!this.selected){
		                $(this).animate({
			                                alpha : kDefaultAlpha
			                              }, 200, "easeOutCirc");
		              }
	              });
	    $(f).bind("didBecomeHovering", function(){
		              if(!this.selected){
		                $(this).animate({
			                                alpha : kHoveringAlpha
			                              }, 200, "easeInCirc");
		              }
	              });
	  }
  }



  var contextPosition = jContextEl.offset();
  jContextEl.mousemove(function(e){
	                       var rx = e.pageX - contextPosition.left;
	                       var ry = e.pageY - contextPosition.top;
	                       for(var factionName in Faction.all){
	                         var faction = Faction.all[factionName];
	                         var over = faction.hovering;
	                         faction.setHovering(pointInRect(rx, ry, faction.x, faction.y, faction.width, faction.height));
	                         triggerOneOfPairIsTrue(over, faction.hovering, "mouseDidEnter", "mouseDidLeave", faction);  
	                       }
	                       idleTime = 0;
                       });
  jContextEl.mousedown(function(e){
	                       var rx = e.pageX - contextPosition.left;
	                       var ry = e.pageY - contextPosition.top;
	                       for(var factionName in Faction.all){
	                         var faction = Faction.all[factionName];
	                         var isInRegion = pointInRect(rx, ry, faction.x, faction.y, faction.width, faction.height);
	                         faction.setSelected(isInRegion && !faction.selected);
	                         if(isInRegion){
		                         $(faction).trigger("mouseDown");
	                         }
	                       }
	                       idleTime = 0;
                       });
  function moveToNextItemInTour(){
          var ff = crosshair.focusedFaction;
          var udf;
          var fidx = (ff == udf || ff == null) ? 0 : ff.index;
          if( (fidx + 1) >= Faction.list.length){
            fidx = 0;
          } else {
            fidx += 1;
          } 
          var f = Faction.list[fidx];
          if(!crosshair.visible){
            crosshair.centerOnFaction(f);
            crosshair.fadeIn();
          } else {
            crosshair.moveToFaction(f);
          }
          f.setSelected(true);
	  /*for(var k in Faction.all){
	    var f = Faction.all[k];
	    if(crosshair.focusedFaction != f){
        if(!crosshair.visible){
		      crosshair.centerOnFaction(f);          
          crosshair.fadeIn();
        }  else {
          crosshair.moveToFaction(f);
        }
        f.setSelected(true);                  
		    break;
	    } 
	    
	  }*/	
  }

	var update = function _updateLoop(step){
  var meridiemMaskWidth = meridiemMask == null ? 0 : meridiemMask.width;
  var meridiemMaskHeight = meridiemMask == null ? 0 : meridiemMask.height;
  var meridiemStep = meridiemMaskWidth * 0.05;
    var frac = step / 1000;
	  context.clearRect(0, 0, width, height);
	  context.drawImage(mapBg, 0, 0, width, height);
    var meridiemSlice = [meridiemMaskWidth - meridiemOffset, meridiemMaskHeight];
    if(meridiemSlice[0] > width){
      meridiemSlice[0] = width;
    }
    if(meridiemMask != null){
    context.drawImage(meridiemMask, meridiemOffset, 0.0, meridiemSlice[0], meridiemSlice[1], 0.0, 0.0, meridiemSlice[0], meridiemSlice[1]);
    if(meridiemSlice[0] < width){
      var remainderOfMask = meridiemMask.width - meridiemOffset;      
      var remainder =  width - remainderOfMask;
      var widthToUse = (remainder > width) ? width : remainder;
      context.drawImage(meridiemMask, 0.0, 0.0, widthToUse, meridiemSlice[1], remainderOfMask - 0.4, 0.0, widthToUse + 1, meridiemSlice[1]);
    }
    meridiemOffset += meridiemStep * frac;
    if(meridiemOffset >= meridiemMask.width){
      meridiemOffset = 0;
    }
    }
    if(!document.all){
	  scanline.draw(context, width, height);
    }
	  for(var factionName in Faction.all){
		  var faction = Faction.all[factionName];
		  if(faction.visible){
		    drawImageWithAlpha(context, faction.image, faction.x, faction.y, faction.width, faction.height, faction.alpha);
		  }
	  } 
	  if(crosshair.visible){
		  crosshair.draw(context, width, height);
	  }

	};
	setInterval(function(){
	              var step = framerate;
	              var t = new Date().getTime();	
	              if(lastUpdate != null){
		              step = t - lastUpdate;
	              }
	              lastUpdate = t;
	              update(step);
	              idleTime += step;
		      if(!document.all){
			  scanLineWaited += step;
			  if(scanLineWaited >= scanLineWaitTime){
		              $(scanline).animate({
				      x : (-scanline.width)
					  }, scanLinePassTime, "easeInOutCirc", function(){
				      this.x = width;
				  });
		              scanLineWaited = 0;
			  }
		      }
	              var oldTour = tourIsRunning;
	              tourIsRunning = idleTime >= timeToWaitForTour;
	              if(oldTour != tourIsRunning && tourIsRunning){
		              moveToNextItemInTour();
		              idleTime = 0;
	              }
	              
	            }, framerate);	
}


function preloadImages(){
  initImage("images/map/Map.jpg");
  if(document.all)
    initImage("images/map/MeridiemMask.png");
  initImage("images/map/gradient-scanline.png");
  initImage("images/map/circle.png");
}
preloadImages();
jQuery(window).load(MapInit);
