// Add ajaxWait
;(function($){var ajaxWaiters=[];$().bind('ajaxError ajaxComplete',function(event,xhr,settings){var currentWaiters=ajaxWaiters.slice();for(var 
i=0;i<currentWaiters.length;i++){currentWaiters[i](event,xhr,settings);}});$.extend({ajaxWait:function(func,callbacks){var urls=[];var ajax=$.ajax;$.ajax=function(settings){var 
value=ajax(settings);if(typeof(value)!='boolean'||value!=false){urls.push(settings.url);}
return value;};var ajaxCallback=function(event,xhr,settings){var 
index=$.inArray(settings.url,urls);if(index>=0){urls.splice(index,1);if(urls.length==0||event.type=='ajaxError'){$.ajax=ajax;ajaxWaiters.splice($.inArray(ajaxWaiters,ajaxCallback),1);if(event.type=='ajaxComplete'&&callbacks.success){callbacks.success();}else 
if(event.type=='ajaxError'&&callbacks.error){callbacks.error();}}}};ajaxWaiters.unshift(ajaxCallback);func();if(urls.length==0){if(callbacks.success){callbacks.success();}
$.ajax=ajax;ajaxWaiters.splice($.inArray(ajaxWaiters,ajaxCallback),1);}
return this;}});})(jQuery);

(function($) {
  // Available markets
  var markets = {};
  markets['RESTful controller'] = {
    projects: ['giraffesoft/resource_controller', 'josevalim/inherited_resources', 'hcatlin/make_resourceful', 'ianwhite/resources_controller'],
    labelWidth: 180
  };
  markets['authentication'] = {
    projects: ['technoweenie/restful-authentication', 'binarylogic/authlogic', 'thoughtbot/clearance'],
    labelWidth: 220
  };
  markets['fixtures replacement'] = {
    projects: ['thoughtbot/factory_girl', 'notahat/machinist', 'flogic/object_daddy'],
    labelWidth: 135
  };
  markets['queuing'] = {
    projects: ['tobi/delayed_job', 'starling/starling', 'kr/beanstalkd'],
    labelWidth: 102
  };
  markets['REST client'] = {
    projects: ['jnunemaker/httparty', 'adamwiggins/rest-client'],
    labelWidth: 145
  };
  markets['file upload'] = {
    projects: ['thoughtbot/paperclip', 'technoweenie/attachment_fu'],
    labelWidth: 175
  };
  markets['state machine'] = {
    projects: ['pluginaweek/state_machine', 'rubyist/aasm', 'ryan-allen/workflow', 'avdi/alter-ego'],
    labelWidth: 170
  };
  markets['gem creation'] = {
    projects: ['technicalpickles/jeweler', 'drnic/newgem', 'seattlerb/hoe', 'fauna/echoe'],
    labelWidth: 145
  };
  markets['exception notification'] = {
    projects: ['thoughtbot/hoptoad_notifier', 'rails/exception_notification', 'contrast/exceptional', 'defunkt/exception_logger'],
    labelWidth: 165
  };
  markets['random data generator'] = {
    projects: ['sevenwire/forgery', 'yyyc514/faker'],
    labelWidth: 110
  };
  markets['mocking framework'] = {
    projects: ['btakita/rr', 'floehopper/mocha', 'jeremymcanally/stump', 'jimweirich/flexmock'],
    labelWidth: 140
  };
  
  // Followers for each project
  var followers = {};
  for (var market in markets) {
    var projects = markets[market].projects;
    for (var i = 0; i < projects.length; i++) {
      followers[projects[i]] = 0;
    }
  }
  
  // The order in which search requests are made
  var requests = [
    ['resource_controller', 'inherited_resources', 'make_resourceful', 'resources_controller', 'restful-authentication', 'authlogic', 'clearance', 'factory_girl', 'machinist', 'object_daddy', 'delayed_job', 'starling', 'beanstalkd', 'httparty', 'rest-client', 'paperclip'],
    ['attachment_fu', 'state_machine', 'aasm', 'workflow', 'alter-ego', 'jeweler', 'newgem', 'echoe', 'hoptoad_notifier', 'exception_notification', 'exceptional', 'exception_logger', 'forgery', 'faker', 'rr', 'mocha', 'stump'],
    ['hoe', 'flexmock']
  ];
  
  // Have followers been loaded yet?
  var loaded = false;
  var counter = 0;
  
  // Process GitHub search results
  function processResults(repositories) {
    repositories = repositories.repositories;
    
    for (var i = 0; i < repositories.length; i++) {
      repository = repositories[i];
      var path = repository.username + '/' + repository.name;
      
      if (path in followers) {
        followers[path] = parseInt(repository.followers);
      }
    }
  }
  
  // Load the market data
  function loadMarkets(callbacks) {
    var successCallback = callbacks.success;
    callbacks.success = function() {
      loaded = true;
      successCallback();
    };
    
    if (!loaded) {
      $.ajaxWait(function() {
        // Request the project information
        for (var i = 0; i < requests.length; i++) {
          var query = '';
          var projectNames = requests[i];
          
          $.ajax({
            type: 'GET',
            url: 'http://github.com/api/v1/json/search/' + projectNames.join(' OR '),
            success: processResults,
            dataType: 'jsonp'
          });
        }
      }, callbacks);
    } else {
      successCallback();
    }
  }
  
  $.extend({
    // Generate market graphs in the given target
    rubyMarkets: function(target, names) {
      if (!names) { names = ['RESTful controller', 'authentication', 'fixtures replacement', 'queuing', 'REST client', 'file upload', 'state machine', 'gem creation', 'exception notification', 'random data generator', 'mocking framework']; }
      var $target = $(target);
      
      var totalHeight = 0;
      for (var i = 0; i < names.length; i++) {
        totalHeight += markets[names[i]].projects.length * 18 + (i == names.length - 1 ? 77 : 92); // Chart height + border + margin
      }
      $target.css({width: 552, height: totalHeight}); // width + border
      
      loadMarkets({
        success: function() {
          var targetMarkets = $.map(names, function(name) { return markets[name]; });
          
          for (var i = 0; i < targetMarkets.length; i++) {
            // Generate context params
            var market = targetMarkets[i];
            var name = names[i];
            var projects = market.projects;
            var followerCounts = $.map(projects, function(project) { return followers[project]; });
            var maxCount = Math.ceil(Math.max.apply(this, followerCounts) / 100) * 100;
            maxCount += maxCount / 5; // Add some padding
            var title = 'Which ' + name + ' project will have the most|github watchers by RailsConf 2009?';
            var width = 550;
            var height = 75 + projects.length * 18; // title height + project height
            var interval = parseInt(Math.ceil(maxCount / 500)) * 50; // increments divisible by 50
            var labelWidth = Math.max.apply(this, $.map(targetMarkets, function(market) { return market.labelWidth; }));
            
            var params = {
              cht: 'bhs',
              chs:  width + 'x' + height,
              chco: '680000',
              chxr: '0,0,' + projects.length + '|1,0,' + maxCount + ',' + interval,
              chds: '0,' + maxCount,
              chxs: '0,000000,13,-1|1,000000,13,-1',
              chts: '000000,12',
              chbh: '12,7,20',
              chma: labelWidth + ',10,10,10',
              chxt: 'y,x',
              chm: 'N ,000000,0,-1,14',
              chd: 't:' + followerCounts.join(','),
              chxl: '0:|' + projects.reverse().join('|'),
              chtt: title
            };
            
            // Add google chart
            var id = counter += 1;
            var $market = $('<div />')
              .addClass('inkling_market')
              .css({height: height + (i == names.length - 1 ? 0 : 17)}) // Border (2) + margin
              .append(
                $('<img />')
                  .attr({
                    src: 'http://chart.apis.google.com/chart?' + $.param(params),
                    alt: title,
                    title: title,
                    useMap: '#inkling_market-' + id + '-' + i
                  })
                  .css({
                    border: '1px solid #cccccc',
                    width: width,
                    height: height
                  })
              )
              .appendTo($target);
            
            var $map = $('<map name="inkling_market-' + id + '-' + i + '" />').appendTo($market);
            
            projects = projects.reverse();
            for (var j = 0; j < projects.length; j++) {
              var y = (46 + j * 18);
              
              $(document.createElement('area'))
                .attr({
                  shape: 'rect',
                  coords: '0,' + y + ',' + labelWidth + ',' + (y + 18),
                  href: 'http://github.com/' + projects[j],
                  alt: projects[j]
                })
                .appendTo($map);
            }
          }
        },
        error: function() {
          // Error: just show a message
          $target.text('There was an error loading the GitHub data!');
        }
      });
    }
  });
})(jQuery);
