(function($) {
  function cancelModal(overlay) {
    return function() {
      overlay.next().fadeOut(200);
      overlay.fadeOut(200, function() {
        overlay.next().remove();
        overlay.remove();
      });
    }
  }

  function adjustSize(overlay) {
    return function() {
      overlay.css({
        top: '0px',
        left: '0px',
        width: '100%',
        height: '100%'
      });

      var item = overlay.next();
      item.css({
        top: (($(window).height() - item.height()) / 2) + 'px',
        left: (($(window).width() - item.width()) / 2) + 'px'
      })
    }
  }

  function createOverlayElem(options) {
    var elem = $('<div></div>');
    elem.addClass('overlay-background');
    elem.css({
      position: 'fixed',
      backgroundColor:  options.backgroundColor   || '#000',
      opacity:          options.backgroundOpacity || 0.6
    });

    var handler = adjustSize(elem); handler.call();

    $(window).bind('resize', handler)

    return elem;
  }

  function createModalOverlay(builder, options) {
    var overlayElem = createOverlayElem(options || {});
    var cancel = cancelModal(overlayElem);
    var overlayItem = builder(cancel);
    overlayItem.css({ visibility: 'hidden', display: 'block' });

    $(document.body).append(overlayElem);
    $(document.body).append(overlayItem)
    $(overlayItem).bind('escape', cancel);

    overlayElem.css({ zIndex: 0 });
    overlayItem.css({
      zIndex: 100,
      position: 'absolute',
      top: (($(window).height() - overlayItem.height()) / 2) + 'px',
      left: (($(window).width() - overlayItem.width()) / 2) + 'px',
      display: 'none',
      visibility: 'visible'
    });

    overlayItem.fadeIn(200);
  }

  function escape(event) {
    if (event.which == 27) {
      $('*').trigger('escape');
    }
  }

  $('*').live('keydown', escape);

  $.modal = createModalOverlay;
})(jQuery);
