(function ($) {

var chipsHandleEvents = false;
var materialChipsDefaults = {
  data: [],
  placeholder: '',
  secondaryPlaceholder: '',
};

$(document).ready(function() {
  // Handle removal of static chips.
  $(document).on('click', '.chip .close', function(e){
    var $chips = $(this).closest('.chips');
    if ($chips.attr('data-initialized')) {
      return;
    }
    $(this).closest('.chip').remove();
  });
});

$.fn.material_chip = function (options) {
  var self = this;
  this.$el = $(this);
  this.$document = $(document);
  this.SELS = {
    CHIPS: '.chips',
    CHIP: '.chip',
    INPUT: 'input',
    DELETE: '.material-icons',
    SELECTED_CHIP: '.selected',
  };

  if ('data' === options) {
    return this.$el.data('chips');
  }

  var curr_options = $.extend({}, materialChipsDefaults, options);

  // Initialize
  this.init = function() {
    var i = 0;
    var chips;
    self.$el.each(function(){
      var $chips = $(this);
      var chipId = Materialize.guid();

      if (!curr_options.data || !(curr_options.data instanceof Array)) {
        curr_options.data = [];
      }
      $chips.data('chips', curr_options.data);
      $chips.attr('data-index', i);
      $chips.attr('data-initialized', true);

      if (!$chips.hasClass(self.SELS.CHIPS)) {
        $chips.addClass('chips');
      }

      self.chips($chips, chipId);
      i++;
    });
  };

  this.handleEvents = function(){
    var SELS = self.SELS;

    self.$document.off('click.chips-focus', SELS.CHIPS).on('click.chips-focus', SELS.CHIPS, function(e){
      $(e.target).find(SELS.INPUT).focus();
    });

    self.$document.off('click.chips-select', SELS.CHIP).on('click.chips-select', SELS.CHIP, function(e){
      $(SELS.CHIP).removeClass('selected');
      $(this).toggleClass('selected');
    });

    self.$document.off('keydown.chips').on('keydown.chips', function(e){
      if ($(e.target).is('input, textarea')) {
        return;
      }

      // delete
      var $chip = self.$document.find(SELS.CHIP + SELS.SELECTED_CHIP);
      var $chips = $chip.closest(SELS.CHIPS);
      var length = $chip.siblings(SELS.CHIP).length;
      var index;

      if (!$chip.length) {
        return;
      }

      if (e.which === 8 || e.which === 46) {
        e.preventDefault();

        index = $chip.index();
        self.deleteChip(index, $chips);

        var selectIndex = null;
        if ((index + 1) < length) {
          selectIndex = index;
        } else if (index === length || (index + 1) === length) {
          selectIndex = length - 1;
        }

        if (selectIndex < 0) selectIndex = null;

        if (null !== selectIndex) {
          self.selectChip(selectIndex, $chips);
        }
        if (!length) $chips.find('input').focus();

      // left
      } else if (e.which === 37) {
        index = $chip.index() - 1;
        if (index < 0) {
          return;
        }
        $(SELS.CHIP).removeClass('selected');
        self.selectChip(index, $chips);

      // right
      } else if (e.which === 39) {
        index = $chip.index() + 1;
        $(SELS.CHIP).removeClass('selected');
        if (index > length) {
          $chips.find('input').focus();
          return;
        }
        self.selectChip(index, $chips);
      }
    });

    self.$document.off('focusin.chips', SELS.CHIPS + ' ' + SELS.INPUT).on('focusin.chips', SELS.CHIPS + ' ' + SELS.INPUT, function(e){
      var $currChips = $(e.target).closest(SELS.CHIPS);
      $currChips.addClass('focus');
      $currChips.siblings('label, .prefix').addClass('active');
      $(SELS.CHIP).removeClass('selected');
    });

    self.$document.off('focusout.chips', SELS.CHIPS + ' ' + SELS.INPUT).on('focusout.chips', SELS.CHIPS + ' ' + SELS.INPUT, function(e){
      var $currChips = $(e.target).closest(SELS.CHIPS);
      $currChips.removeClass('focus');

      // Remove active if empty
      if (!$currChips.data('chips').length) {
        $currChips.siblings('label').removeClass('active');
      }
      $currChips.siblings('.prefix').removeClass('active');
    });

    self.$document.off('keydown.chips-add', SELS.CHIPS + ' ' + SELS.INPUT).on('keydown.chips-add', SELS.CHIPS + ' ' + SELS.INPUT, function(e){
      var $target = $(e.target);
      var $chips = $target.closest(SELS.CHIPS);
      var chipsLength = $chips.children(SELS.CHIP).length;

      // enter
      if (13 === e.which) {
        e.preventDefault();
        self.addChip({tag: $target.val()}, $chips);
        $target.val('');
        return;
      }

      // delete or left
       if ((8 === e.keyCode || 37 === e.keyCode) && '' === $target.val() && chipsLength) {
        self.selectChip(chipsLength - 1, $chips);
        $target.blur();
        return;
      }
    });

    // Click on delete icon in chip.
    self.$document.off('click.chips-delete', SELS.CHIPS + ' ' + SELS.DELETE).on('click.chips-delete', SELS.CHIPS + ' ' + SELS.DELETE, function(e) {
      var $target = $(e.target);
      var $chips = $target.closest(SELS.CHIPS);
      var $chip = $target.closest(SELS.CHIP);
      e.stopPropagation();
      self.deleteChip($chip.index(), $chips);
      $chips.find('input').focus();
    });
  };

  this.chips = function($chips, chipId) {
    var html = '';
    $chips.data('chips').forEach(function(elem){
      html += self.renderChip(elem);
    });
    html += '<input id="' + chipId +'" class="input" placeholder="">';
    $chips.html(html);
    self.setPlaceholder($chips);

    // Set for attribute for label
    var label = $chips.next('label');
    if (label.length) {
      label.attr('for', chipId);

      if ($chips.data('chips').length) {
        label.addClass('active');
      }
    }
  };

  this.renderChip = function(elem) {
    if (!elem.tag) return;

    var html = '<div class="chip">' + elem.tag;
    if (elem.image) {
      html += ' <img src="' + elem.image + '"> ';
    }
    html += '<i class="material-icons close">close</i>';
    html += '</div>';
    return html;
  };

  this.setPlaceholder = function($chips) {
    if ($chips.data('chips').length && curr_options.placeholder) {
      $chips.find('input').prop('placeholder', curr_options.placeholder);

    } else if (!$chips.data('chips').length && curr_options.secondaryPlaceholder) {
      $chips.find('input').prop('placeholder', curr_options.secondaryPlaceholder);
    }
  };

  this.isValid = function($chips, elem) {
    var chips = $chips.data('chips');
    var exists = false;
    for (var i=0; i < chips.length; i++) {
      if (chips[i].tag === elem.tag) {
          exists = true;
          return;
      }
    }
    return '' !== elem.tag && !exists;
  };

  this.addChip = function(elem, $chips) {
    if (!self.isValid($chips, elem)) {
      return;
    }
    var chipHtml = self.renderChip(elem);
    var newData = [];
    var oldData = $chips.data('chips');
    for (var i = 0; i < oldData.length; i++) {
      newData.push(oldData[i]);
    }
    newData.push(elem);

    $chips.data('chips', newData);
    $(chipHtml).insertBefore($chips.find('input'));
    $chips.trigger('chip.add', elem);
    self.setPlaceholder($chips);
  };

  this.deleteChip = function(chipIndex, $chips) {
    var chip = $chips.data('chips')[chipIndex];
    $chips.find('.chip').eq(chipIndex).remove();

    var newData = [];
    var oldData = $chips.data('chips');
    for (var i = 0; i < oldData.length; i++) {
      if (i !== chipIndex) {
        newData.push(oldData[i]);
      }
    }

    $chips.data('chips', newData);
    $chips.trigger('chip.delete', chip);
    self.setPlaceholder($chips);
  };

  this.selectChip = function(chipIndex, $chips) {
    var $chip = $chips.find('.chip').eq(chipIndex);
    if ($chip && false === $chip.hasClass('selected')) {
      $chip.addClass('selected');
      $chips.trigger('chip.select', $chips.data('chips')[chipIndex]);
    }
  };

  this.getChipsElement = function(index, $chips) {
    return $chips.eq(index);
  };

  // init
  this.init();

  if (!chipsHandleEvents) {
    this.handleEvents();
    chipsHandleEvents = true;
  }
};

}( jQuery ));