/**
 * Collection of internally used jQuery plugins
 * developed in house
 *
 * @author Damian Galarza (damian@thrillist.com)
 */
(function() {

  var supports_placeholder = function() {
    var el = document.createElement('input');
    return 'placeholder' in el;
  };

  var build_pw_placeholder = function($original) {
    var el = document.createElement('input');
    el.setAttribute('type', 'text');
    el.className = $original[0].className + ' placeholder';
    el.style.display = 'none';
    el.disabled = true;
    el.value = $original.attr('placeholder');
    el.setAttribute('tabIndex', $original.attr('tabIndex'));

    return el;
  };

  /**
   * Handle backward compatiblity of the HTML5 placeholder attribute on inputs
   * Makes use of a dummy input for password fields to display the placeholder in
   */
  $.fn.placeHolder = function() {

    // Allow native browser support to take precedence
    if (supports_placeholder()) return this;

    return this.each(function(i) {

      var $this = $(this);
      var is_password = this.type === 'password';
      var placeholder = $this.attr('placeholder');

      if (placeholder === undefined || placeholder === '') return;

      if (is_password) {
        var pw = build_pw_placeholder($this);
        var $pw = $(pw);

        $this.parent().append(pw);
      }

      if ($this.val() === '') {
        if (is_password) {
          $this.hide();
          $pw.show();
          pw.disabled = false;
        }
        else {
          $this.val(placeholder).addClass('placeholder');
        }
      }
      
      if (is_password) {

        $pw.bind('focus.tl_placeholder', function() {
          $pw.hide();
          $this.show().focus();
        });

      }
      else {
      
        $this.bind('focus.tl_placeholder', function() {
          var $this = $(this);

          $this.removeClass('placeholder');

          if ($this.val() === $this.attr('placeholder')) {
            $this.val(''); 
          }
        });

      }

      $this.bind('blur.tl_placeholder', function() {
        var $this = $(this);

        if ($this.val() === '') {

          if (is_password) {
            $this.hide();
            pw.disabled = false;
            $pw.show();
          }
          else {
            $this.val($this.attr('placeholder'));
            $this.addClass('placeholder');
          }

        }
        else if (is_password) {
          pw.disabled = true;
        }

      });

    });

  };

  var checkbox_replacement = function(checked, parent_id) {
    var el = document.createElement('span');
    var css_classes = ['jt-fake-checkbox'];

    if (checked) {
      css_classes.push('is-checked');
    }

    if (parent_id.length > 0) {
      el.setAttribute('data-parent', parent_id);
    }
    
    el.className = css_classes.join(' ');

    return el;
  };

  var fake_checkbox_click = function(e) {
    e.preventDefault();

    var $this = $(this);

    // Get the fake checkbox if the label was clicked instead
    if (this.tagName !== 'span') {
      $this = $this.parent().find('span.jt-fake-checkbox');
    }

    var $checkbox = $this.parent().find('input[type=checkbox]');

    if ($checkbox[0].checked) {
      $this.removeClass('is-checked');
      $checkbox[0].checked = false;
    }
    else {
      $this.addClass('is-checked');
      $checkbox[0].checked = true;
    }

  };

  // Jackthreads Custom Checkboxes
  $.fn.jt_pretty_checkbox = function() {
    return this.each(function(i) {

      var $this = $(this);
      var fake = checkbox_replacement(this.checked, this.id);

      $this.hide();
      $this.before(fake);

      // Enable label functionality
      if (this.id) {
        $this.parent().find('label[for=' + this.id + ']').bind('click', fake_checkbox_click);
      }

      $(fake).bind('click', fake_checkbox_click);

    });
  };

  var jt_radio = {
    
    checked_class: 'is-checked',
    focused_class: 'in-focus',

    wrapper_template: null,

    build: function(parent) {

      var wrapper = jt_radio.build_wrapper();
      var el = document.createElement('span');

      var clean_group = jt_radio.query_friendly_class(parent.name);
      var group_class = 'radio-group-' + clean_group;

      var class_string = ['jt-radio', group_class];

      if (parent.defaultChecked) {
        class_string.push(jt_radio.checked_class);
      }

      el.className = class_string.join(' ');

      var identifiers = {
        'parent': parent.id,
        'group': clean_group
      };

      for (var prop in identifiers) { el.setAttribute('data-' + prop, identifiers[prop]); }

      el.id = jt_radio.generate_id(parent.id);

      wrapper.appendChild(el);

      return {
        el: el,
        wrapper: wrapper
      }

    },

    build_wrapper: function() {
      var template = jt_radio.wrapper_template;
      if (!template) {
        template = jt_radio.wrapper_template = document.createElement('div');
        template.className = 'jt-radio-field';
      }

      return template.cloneNode(true); 
    },

    query_friendly_class: function(input_name) {
      var class_name = input_name.replace('data[', '');
      class_name = class_name.replace(/(\[)/g, '-');
      class_name = class_name.replace(/(\])/g, '');

      return class_name.toLowerCase();
    },

    uncheck_group: function(group_name) {
      var qs = '.jt-radio.radio-group-' + group_name;
      $(qs).removeClass(this.checked_class);
    },

    generate_id: function(parent_id) {
      return parent_id + '-jt-radio';
    },

    check: function() {
      var group_name = this.getAttribute('data-group');
      jt_radio.uncheck_group(group_name);
      
      var parent_id = this.getAttribute('data-parent');
      document.getElementById(parent_id).checked = true;

      $(this).addClass(jt_radio.checked_class);
    },
    
    get_by_input: function(input) {
      var $jt_radio = $('#' + input.getAttribute('data-jt-radio'));
      return $jt_radio;
    }
    
  };

  $.fn.jt_radio = function() {

    return this.each(function(i) {

      var $this = $(this);

      var radio = jt_radio.build(this);
      var fake_radio = radio.el;

      this.setAttribute('data-group', fake_radio.getAttribute('data-group'));
      this.setAttribute('data-jt-radio', fake_radio.getAttribute('id'));

      $this.bind({

        'change.jt-radio': function() {

          jt_radio.uncheck_group(this.getAttribute('data-group'));

          var $jt_select = $('#' + this.id + '-jt-radio');
          var checked_class = jt_radio.checked_class;

          if (this.checked) {
            $jt_select.addClass(checked_class);
          }
          else {
            $jt_select.removeClass(checked_class);
          }

        },

        'focus.jt-radio': function() {
          var focused_class = jt_radio['focused_class'];
          var $jt_radio = jt_radio.get_by_input(this);

          $jt_radio.addClass(focused_class);
        },

        'blur.jt-radio': function() {
          var focused_class = jt_radio['focused_class'];
          var $jt_radio = jt_radio.get_by_input(this);

          $jt_radio.removeClass(focused_class);
        }

      });

      $(fake_radio).bind('click.jt-radio', jt_radio.check);
      $this.before(radio.wrapper);
      radio.wrapper.appendChild(this);

    });
  };
  
  /**
   * Vertically align elements
   *
   * @param [Boolean] (optional) Use outer height to determine parent's height?
   */
  $.fn.vAlign = function(use_outer) {
    return this.each(function(i) {
      
      var $this = $(this);
      var height = $this.height();

      var parent_height = (use_outer) ? $this.parent().outerHeight() : $this.parent().height();

      var difference = parent_height - height;
      var offset = Math.ceil(difference / 2);

      $this.css('margin-top', offset);

    });
  };

  $(function() {
    $('[placeholder]').placeHolder();
    $('input[type=radio]').jt_radio();
  });

  
})();

