jQuery(function($) {
  var parseFloat = function(s) {
    s = s.replace(/[^\d+-.]+/g, "");
    return s && window.parseFloat(s);
  };
  var parseInt = function(s) {
    s = s.replace(/[^\d+-.]+/g, "");
    return s && window.parseInt(s);
  };
  var Min = function(x) {
    if (arguments.length === 1 && x instanceof Array)
      return Math.min.apply(Math, x);
    return Math.min.apply(Math, arguments);
  };
  var Max = function(x) {
    if (arguments.length === 1 && x instanceof Array)
      return Math.max.apply(Math, x);
    return Math.max.apply(Math, arguments);
  };

  function foreach(f) {
    return function() { 
      var args = arguments;
      return $(this).each(function() {
        return f.apply(this, args);
      });
    }
  }

  // popup
  $("#popup").css("opacity", 0.9);
  var timeoutrole = "hide";
  var timeout = setTimeout($.noop, 1);
  function popup(x, y, title, content) {
    var $popup = $("#popup");
    if (arguments.length === 0) {
      clearTimeout(timeout);
      timeoutrole = "hide";
      timeout = setTimeout(function() { $popup.fadeOut(); }, 100);
      return;
    }
    (timeoutrole === "hide") && clearTimeout(timeout);
    if (arguments.length > 2) {
      clearTimeout(timeout);
      timeoutrole = "role";
      timeout = setTimeout(function() { 
        var $body = $popup.children("div.popup-body").empty()
        if (content instanceof Function) {
          content($body);
        } else
          $body.append(content);
        $popup.children("h1").text(title);
        $popup.stop();
        $popup.show().css("opacity", 0.9);
      }, 10);
    }
    $popup.css({left: x-280, top: y-190});
    return $popup;
  };

  function constantly(x) {
    return function() { return x };
  }

  $.fn.popup = function(datafn) {
    if (arguments.length === 2) 
      datafn = constantly({title: arguments[0], body: arguments[1]});
    $(this).bind("mouseenter", function(e) {
      var data = datafn(this);
      popup(e.pageX, e.pageY, data.title, data.body);
    }).bind("mouseleave", function(e) {
      popup();
    }).bind("mousemove", function(e) {
      popup(e.pageX, e.pageY);
    });  
  };

  $.fn.popupLive = function(datafn) {
    if (arguments.length === 2) 
      datafn = constantly({title: arguments[0], body: arguments[1]});
    $(this).live("mouseenter", function(e) {
      var data = datafn(this);
      popup(e.pageX, e.pageY, data.title, data.body);
    }).live("mouseleave", function(e) {
      popup();
    }).live("mousemove", function(e) {
      popup(e.pageX, e.pageY);
    });  
  };
  // end popup

  $.fn.scrape = function(cells) {
    return $(this).map(cells ? function() {
      return [$(this).find(cells).scrape()];
    } : function() {
      return parseFloat($(this).text());
    }).get();
  }

  function hsl2rgb(h, s, l) {
    var c = l <= 0.5 ? 2*l*s : 2*(1-l)*s;
    var hp = h / 60;
    var x = c*(1 - Math.abs(hp%2 - 1));
    var r = 0, g = 0, b = 0;
    if (hp < 1) {
      r = c; g = x;
    } else if (hp < 2) {
      r = x; g = c;
    } else if (hp < 3) {
      g = c; b = x;
    } else if (hp < 4) {
      g = x; b = c;
    } else if (hp < 5) {
      r = x; b = c;
    } else {
      r = c; b = x;
    }
    var m = l - 0.5*c;
    r+=m; g+=m; b+=m;
    return "rgb(" + Math.floor(r*255.99) + "," 
                  + Math.floor(g*255.99) + "," + Math.floor(b*255.99) + ")";
  }

  function hashcolor(s, l) {
    l = l || 0.5
    s = $.trim(s);
    var h = s.length*60;
    for(var i = 0; i < s.length; i++) {
      h += (s.charCodeAt(i)-32)*31;
    }
   return hsl2rgb(h%360, 1, l);
  }

  // here starts the new lean svgmap plugin
  function getstyle($e) {
    var s = $e.attr("style");
    var r = {};
    var fill = $e.attr("fill");
    var stroke = $e.attr("stroke");
    if (fill) r.fill = fill;
    if (stroke) r.stroke = stroke;
    s && s.replace(/(\w+)\s*:\s*([^;]*[^\s;])/g, function(x, name, value) {
      r[name] = value;
      return x;
    });
    return r;
  }
 
  $.fn.svgmap = function(url, callback) {
   return $(this).each(function() {
    var $this = $(this);
    var that = this;
    $.get(url, function(svg) {
      var $svg = $(svg);
      var sc;
      var vb = $svg.find("svg").attr("viewBox");
      if (vb) 
        $this.R(function(paper) {
          vb = vb.split(/\s+/);
          sc = Min(paper.dims.w/vb[2], paper.dims.h/vb[3]);
        });
      
      $svg.find("path").each(function() {
        var $path = $(this);
        var style = getstyle($path);
        var id = $path.attr("id");
        var name = id ? "country #" + id : "country";
        
        var d = $path.attr("d");
        d && $this.draw(name, "path", [d],
          function(p) {
            p.attr({fill: style.fill || "none", 
                    stroke: style.stroke || "none"});
            var t = $path.attr("transform");
            if (t && (t = /(\w+)\((.*)\)/.exec(t))) {
              var args = t[2].split(/\s*,\s*/);
              var t = t[1];
              if (t === "scale") {
                if (args.length === 1) args[1] = args[0];
                if (sc) {
                  args[0] *= sc;
                  args[1] *= sc;
                }
                args.push(0, 0);
              }
              if (t !== "matrix") {
                p[t] && p[t].apply(p, args);
              } else {
                if (args[1] == 0 && args[2] == 0) {
                  p.scale(sc*args[0], sc*args[3], 0, 0).translate(args[4]*sc, args[5]*sc);
                } else if (console)
                  console.log("unsupported transform on #"+id+": "+t+"("+args.join(",")+")");
              }
            } else {
              p.scale(sc, sc, 0, 0);
            }
        }); 
      });
      callback && callback.call(that, svg);
    });
   });
  };
  // end of the plugin


});

