'use strict';

(function ($) {

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

  $(document).ready(function () {
    // Handle removal of static chips.
    $(document).on('click', '.chip .close', function () {

      var $this = $(this);
      var $chips = $this.closest('.chips');

      if ($chips.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: '.fa',
      SELECTED_CHIP: '.selected'
    };

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

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

    this.$el.data('options', $.extend({}, materialChipsDefaults, options));

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

        var $chips = $(this);
        if ($chips.data('initialized')) {
          return;
        } // Prevent double initialization.

        var options = $chips.data('options');
        if (!options.data || !(options.data instanceof Array)) {
          options.data = [];
        }

        $chips.data('chips', options.data);
        $chips.data('index', i);
        $chips.data('initialized', true);

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

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

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

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

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

      self.$document.on('keydown', 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 = void 0;

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

        var isBackspaceOrDelete = e.which === 8 || e.which === 46;
        var isLeftArrow = e.which === 37;
        var isRightArrow = e.which === 39;

        if (isBackspaceOrDelete) {
          e.preventDefault();
          var chipsIndex = $chips.data('index');
          index = $chip.index();
          self.deleteChip(chipsIndex, 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 (selectIndex !== null) {
            self.selectChip(chipsIndex, selectIndex, $chips);
          }
          if (!length) {
            $chips.find('input').focus();
          }
        } else if (isLeftArrow) {

          index = $chip.index() - 1;
          if (index < 0) {
            return;
          }
          $(SELS.CHIP).removeClass('selected');
          self.selectChip($chips.data('index'), index, $chips);
        } else if (isRightArrow) {

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

      self.$document.on('focusin', SELS.CHIPS + ' ' + SELS.INPUT, function (e) {
        $(e.target).closest(SELS.CHIPS).addClass('focus');
        $(SELS.CHIP).removeClass('selected');
      });

      self.$document.on('focusout', SELS.CHIPS + ' ' + SELS.INPUT, function (e) {
        $(e.target).closest(SELS.CHIPS).removeClass('focus');
      });

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

        var isEnter = e.which === 13;

        if (isEnter) {
          e.preventDefault();
          self.addChip(chipsIndex, {
            tag: $target.val()
          }, $chips);
          $target.val('');
          return;
        }

        var isLeftArrowOrDelete = e.keyCode === 8 || e.keyCode === 37;
        var isValueEmpty = $target.val() === '';

        if (isLeftArrowOrDelete && isValueEmpty && chipsLength) {
          self.selectChip(chipsIndex, chipsLength - 1, $chips);
          $target.blur();
          return;
        }
      });

      self.$document.on('click', 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($chips.data('index'), $chip.index(), $chips);
        $chips.find('input').focus();
      });
    };

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

    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="close fa fa-times"></i>';
      html += '</div>';
      return html;
    };

    this.setPlaceholder = function ($chips) {
      var options = $chips.data('options');
      if ($chips.data('chips').length && options.placeholder) {
        $chips.find('input').prop('placeholder', options.placeholder);
      } else if (!$chips.data('chips').length && options.secondaryPlaceholder) {
        $chips.find('input').prop('placeholder', 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 (chipsIndex, elem, $chips) {
      if (!self.isValid($chips, elem)) {
        return;
      }

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

    this.deleteChip = function (chipsIndex, chipIndex, $chips) {
      var chip = $chips.data('chips')[chipIndex];
      $chips.find('.chip').eq(chipIndex).remove();
      $chips.data('chips').splice(chipIndex, 1);
      $chips.trigger('chip.delete', chip);
      self.setPlaceholder($chips);
    };

    this.selectChip = function (chipsIndex, chipIndex, $chips) {
      var $chip = $chips.find('.chip').eq(chipIndex);
      if ($chip && $chip.hasClass('selected') === false) {
        $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);