;(function($) {
  
  $.fn.simpleImageCheck = function(o) {
    var n = this;
    if (n.length < 1) { return n; }
    
    // Set up options (and defaults)
    o = (o)?o:{};
    o = auditOptions(o);
    
    n.each(function() {
      var i = $(this);
      if (i.is(':checkbox')) {
        setup(i, o);
      }
    });
    
    return n;
  };
  
  var setup = function(n, o) {
    var c = n.is(':checked');
    var src = o.image;
    if (c) { src = o.imageChecked; }
    
    // set id on input if it doesn't have one
    var id = n.attr('id');
    if (typeof(id) === 'undefined') {
      id = n.attr('id', 'imageCheckInput_'+$.fn.simpleImageCheck.uid++).attr('id');
    }
    
    // use text of label for alt and title on image
    var t = $('label[for="'+id+'"]').text();
    
    // Create image node
    var im = n.before("<img src='"+src+"' id='ic_"+id+"' alt='"+t+"' title='"+t+"' class='imageCheck"+((c)?' checked':'')+"' role='checkbox' aria-checked='"+((c)?'true':'false')+"' aria-controls='"+id+"' />")
              .parent()
                .find('img#ic_'+id);
    
    n
      // attach handlers to the original input node to redirect to ours
      .click(function(e, triggered) {
        // Avoid infinite loop & double checking
        if (triggered === true) { return; }
        handleClick(n, im, o, true);
      })
      .keypress(function(e) {
        var k = (e.which)?e.which:((e.keyCode)?e.keyCode:0);
        // trigger on space or enter keys
        if (k == 13 || k == 32) {
          e.preventDefault();
          $(this).click();
        }
      })
      // Hide the original input box
      .hide();
    
    im
      // make image look 'clickable'
      .css({cursor: 'pointer'})
      // attach handlers to the image
      .click(function(e) {
        e.preventDefault();
        handleClick(n, im, o, false);
      })
      .keypress(function(e) {
        var k = (e.which)?e.which:((e.keyCode)?e.keyCode:0);
        // trigger on space or enter keys
        if (k == 13 || k == 32) {
          e.preventDefault();
          $(this).click();
        }
      })
      // add class to image on hover
      .hover(
        function() {
          $(this).addClass('imageCheckHover');
        },
        function() {
          $(this).removeClass('imageCheckHover');
        }
      );
  }
  
  var handleClick = function(n, im, o, inputClick) {
    // determine if we need to check input box. i.e. if input is 
    // checked and img has 'checked' class, need to flip it
    if (im.hasClass('checked') === n.is(':checked') && !inputClick) {
      n.trigger('click', [true]).change();
    }
    // Now toggle the image source and change attributes to complete the ruse
    var c = n.is(':checked');
    im
      .toggleClass('checked')
      .attr({
        'aria-checked': ''+((c)?'true':'false'),
        'src': ''+((c)?o.imageChecked:o.image)
      });
    
    // Timeout to allow for 'checking' to occur before callback
    setTimeout(function() {  
      o.afterCheck(c);
    }, 25);
  }
  
  // Defined outside simpleImageCheck to allow for usage during construction
  var auditOptions = function(o) {
    if (!$.isFunction(o.afterCheck)) { o.afterCheck = function() {}; }
    if (typeof(o.image) != 'string') { o.image = ''; }
    if (typeof(o.imageChecked) != 'string') { o.imageChecked = ''; }
        
    return o;
  }
  
  // Static properties
  $.fn.simpleImageCheck.uid = 0;
  
})(jQuery);