/*!
 * jQuery pagination plugin v1.4.2
 * http://josecebe.github.io/twbs-pagination/
 *
 * Copyright 2014-2018, Eugene Simakin
 * Released under Apache 2.0 license
 * http://apache.org/licenses/LICENSE-2.0.html
 *
 * This plugin is modified to remove next/prev pagination markup when they are disabled.
 * This plugin should not be updated until applying changes to new version.
 */
(function ($, window, document, undefined) {

  'use strict';

  var old = $.fn.twbsPagination;

  // PROTOTYPE AND CONSTRUCTOR

  var TwbsPagination = function (element, options) {
    this.$element = $(element);
    this.options = $.extend({}, $.fn.twbsPagination.defaults, options);

    if (this.options.startPage < 1 || this.options.startPage > this.options.totalPages) {
      throw new Error('Start page option is incorrect');
    }

    this.options.totalPages = parseInt(this.options.totalPages);
    if (isNaN(this.options.totalPages)) {
      throw new Error('Total pages option is not correct!');
    }

    this.options.visiblePages = parseInt(this.options.visiblePages);
    if (isNaN(this.options.visiblePages)) {
      throw new Error('Visible pages option is not correct!');
    }

    if (this.options.beforePageClick instanceof Function) {
      this.$element.first().on('beforePage', this.options.beforePageClick);
    }

    if (this.options.onPageClick instanceof Function) {
      this.$element.first().on('page', this.options.onPageClick);
    }

    // hide if only one page exists
    if (this.options.hideOnlyOnePage && this.options.totalPages == 1) {
      if (this.options.initiateStartPageClick) {
        this.$element.trigger('page', 1);
      }
      return this;
    }

    if (this.options.href) {
      this.options.startPage = this.getPageFromQueryString();
      if (!this.options.startPage) {
        this.options.startPage = 1;
      }
    }

    var tagName = (typeof this.$element.prop === 'function') ?
      this.$element.prop('tagName') : this.$element.attr('tagName');

    if (tagName === 'UL') {
      this.$listContainer = this.$element;
    } else {
      var elements = this.$element;
      var $newListContainer = $([]);
      elements.each(function (index) {
        var $newElem = $("<ul></ul>");
        $(this).append($newElem);
        $newListContainer.push($newElem[0]);
      });
      this.$listContainer = $newListContainer;
      this.$element = $newListContainer;
    }

    this.$listContainer.addClass(this.options.paginationClass);

    if (this.options.initiateStartPageClick) {
      this.show(this.options.startPage);
    } else {
      this.currentPage = this.options.startPage;
      this.render(this.getPages(this.options.startPage));
      this.setupEvents();
    }

    return this;
  };

  TwbsPagination.prototype = {

    constructor: TwbsPagination,

    destroy: function () {
      this.$element.empty();
      this.$element.removeData('twbs-pagination');
      this.$element.off('page');

      return this;
    },

    show: function (page) {
      if (page < 1 || page > this.options.totalPages) {
        throw new Error('Page is incorrect.');
      }
      this.currentPage = page;

      this.$element.trigger('beforePage', page);

      var pages = this.getPages(page);
      this.render(pages);
      this.setupEvents();

      this.$element.trigger('page', page);

      return pages;
    },

    enable: function () {
      this.show(this.currentPage);
    },

    disable: function () {
      var _this = this;
      this.$listContainer.off('click').on('click', 'li', function (evt) {
        evt.preventDefault();
      });
      this.$listContainer.children().each(function () {
        var $this = $(this);
        if (!$this.hasClass(_this.options.activeClass)) {
          $(this).addClass(_this.options.disabledClass);
        }
      });
    },

    buildListItems: function (pages) {
      var listItems = [];

      if (this.options.first) {
        listItems.push(this.buildItem('first', 1));
      }

      if (this.options.prev) {
        var prev = pages.currentPage > 1 ? pages.currentPage - 1 : this.options.loop ? this.options.totalPages : 1;
        listItems.push(this.buildItem('prev', prev));
      }

      for (var i = 0; i < pages.numeric.length; i++) {
        listItems.push(this.buildItem('page', pages.numeric[i]));
      }

      if (this.options.next) {
        var next = pages.currentPage < this.options.totalPages ? pages.currentPage + 1 : this.options.loop ? 1 : this.options.totalPages;
        listItems.push(this.buildItem('next', next));
      }

      if (this.options.last) {
        listItems.push(this.buildItem('last', this.options.totalPages));
      }

      return listItems;
    },

    buildItem: function (type, page) {
      var $itemContainer = $('<li></li>'),
        $itemContent = $('<a></a>'),
        itemText = this.options[type] ? this.makeText(this.options[type], page) : page;

      $itemContainer.addClass(this.options[type + 'Class']);
      $itemContainer.data('page', page);
      $itemContainer.data('page-type', type);
      $itemContainer.append($itemContent.attr('href', this.makeHref(page)).addClass(this.options.anchorClass).html(itemText));

      return $itemContainer;
    },

    getPages: function (currentPage) {
      var pages = [];

      var half = Math.floor(this.options.visiblePages / 2);
      var start = currentPage - half + 1 - this.options.visiblePages % 2;
      var end = currentPage + half;

      var visiblePages = this.options.visiblePages;
      if (visiblePages > this.options.totalPages) {
        visiblePages = this.options.totalPages;
      }

      // handle boundary case
      if (start <= 0) {
        start = 1;
        end = visiblePages;
      }
      if (end > this.options.totalPages) {
        start = this.options.totalPages - visiblePages + 1;
        end = this.options.totalPages;
      }

      var itPage = start;
      while (itPage <= end) {
        pages.push(itPage);
        itPage++;
      }

      return { "currentPage": currentPage, "numeric": pages };
    },

    render: function (pages) {
      var _this = this;
      this.$listContainer.children().remove();
      var items = this.buildListItems(pages);
      $.each(items, function (key, item) {
        _this.$listContainer.append(item);
      });

      this.$listContainer.children().each(function () {
        var $this = $(this),
          pageType = $this.data('page-type');

        switch (pageType) {
          case 'page':
            if ($this.data('page') === pages.currentPage) {
              $this.addClass(_this.options.activeClass);
            }
            break;
          case 'first':
            $this.toggleClass(_this.options.disabledClass, pages.currentPage === 1);
            break;
          case 'last':
            $this.toggleClass(_this.options.disabledClass, pages.currentPage === _this.options.totalPages);
            break;
          case 'prev':
            if (!_this.options.loop && pages.currentPage === 1) {
              $this.remove();
            }
            break;
          case 'next':
            if (!_this.options.loop && pages.currentPage === _this.options.totalPages) {
              $this.remove();
            }
            break;
          default:
            break;
        }

      });
    },

    setupEvents: function () {
      var _this = this;
      this.$listContainer.off('click').on('click', 'li', function (evt) {
        var $this = $(this);
        if ($this.hasClass(_this.options.disabledClass) || $this.hasClass(_this.options.activeClass)) {
          return false;
        }
        // Prevent click event if href is not set.
        !_this.options.href && evt.preventDefault();
        _this.show(parseInt($this.data('page')));
      });
    },

    changeTotalPages: function (totalPages, currentPage) {
      this.options.totalPages = totalPages;
      return this.show(currentPage);
    },

    makeHref: function (page) {
      return this.options.href ? this.generateQueryString(page) : "#";
    },

    makeText: function (text, page) {
      return text.replace(this.options.pageVariable, page)
        .replace(this.options.totalPagesVariable, this.options.totalPages)
    },

    getPageFromQueryString: function (searchStr) {
      var search = this.getSearchString(searchStr),
        regex = new RegExp(this.options.pageVariable + '(=([^&#]*)|&|#|$)'),
        page = regex.exec(search);
      if (!page || !page[2]) {
        return null;
      }
      page = decodeURIComponent(page[2]);
      page = parseInt(page);
      if (isNaN(page)) {
        return null;
      }
      return page;
    },

    generateQueryString: function (pageNumber, searchStr) {
      var search = this.getSearchString(searchStr),
        regex = new RegExp(this.options.pageVariable + '=*[^&#]*');
      if (!search) return '';
      return '?' + search.replace(regex, this.options.pageVariable + '=' + pageNumber);
    },

    getSearchString: function (searchStr) {
      var search = searchStr || window.location.search;
      if (search === '') {
        return null;
      }
      if (search.indexOf('?') === 0) search = search.substr(1);
      return search;
    },

    getCurrentPage: function () {
      return this.currentPage;
    },

    getTotalPages: function () {
      return this.options.totalPages;
    }
  };

  // PLUGIN DEFINITION

  $.fn.twbsPagination = function (option) {
    var args = Array.prototype.slice.call(arguments, 1);
    var methodReturn;

    var $this = $(this);
    var data = $this.data('twbs-pagination');
    var options = typeof option === 'object' ? option : {};

    if (!data) $this.data('twbs-pagination', (data = new TwbsPagination(this, options)));
    if (typeof option === 'string') methodReturn = data[option].apply(data, args);

    return (methodReturn === undefined) ? $this : methodReturn;
  };

  $.fn.twbsPagination.defaults = {
    totalPages: 1,
    startPage: 1,
    visiblePages: 5,
    initiateStartPageClick: true,
    hideOnlyOnePage: false,
    href: false,
    pageVariable: '{{page}}',
    totalPagesVariable: '{{total_pages}}',
    page: null,
    first: 'First',
    prev: 'Previous',
    next: 'Next',
    last: 'Last',
    loop: false,
    beforePageClick: null,
    onPageClick: null,
    paginationClass: 'pagination',
    nextClass: 'page-item next',
    prevClass: 'page-item prev',
    lastClass: 'page-item last',
    firstClass: 'page-item first',
    pageClass: 'page-item',
    activeClass: 'active',
    disabledClass: 'disabled',
    anchorClass: 'page-link'
  };

  $.fn.twbsPagination.Constructor = TwbsPagination;

  $.fn.twbsPagination.noConflict = function () {
    $.fn.twbsPagination = old;
    return this;
  };

  $.fn.twbsPagination.version = "1.4.2";

})(window.jQuery, window, document);
