text: angular.module('ui.bootstrap.pagination', ['ui.bootstrap.paging'])
  .controller('UibPaginationController', ['$scope', '$attrs', '$parse', 'uibPaging', 'uibPaginationConfig', function($scope, $attrs, $parse, uibPaging, uibPaginationConfig) {
    var ctrl = this;
    // Setup configuration parameters
    var maxSize = angular.isDefined($attrs.maxSize) ? $scope.$parent.$eval($attrs.maxSize) : uibPaginationConfig.maxSize,
      rotate = angular.isDefined($attrs.rotate) ? $scope.$parent.$eval($attrs.rotate) : uibPaginationConfig.rotate,
      forceEllipses = angular.isDefined($attrs.forceEllipses) ? $scope.$parent.$eval($attrs.forceEllipses) : uibPaginationConfig.forceEllipses,
      boundaryLinkNumbers = angular.isDefined($attrs.boundaryLinkNumbers) ? $scope.$parent.$eval($attrs.boundaryLinkNumbers) : uibPaginationConfig.boundaryLinkNumbers;
    $scope.boundaryLinks = angular.isDefined($attrs.boundaryLinks) ? $scope.$parent.$eval($attrs.boundaryLinks) : uibPaginationConfig.boundaryLinks;
    $scope.directionLinks = angular.isDefined($attrs.directionLinks) ? $scope.$parent.$eval($attrs.directionLinks) : uibPaginationConfig.directionLinks;
  
    uibPaging.create(this, $scope, $attrs);
  
    if ($attrs.maxSize) {
      ctrl._watchers.push($scope.$parent.$watch($parse($attrs.maxSize), function(value) {
        maxSize = parseInt(value, 10);
        ctrl.render();
      }));
    }
  
    // Create page object used in template
    function makePage(number, text, isActive) {
      return {
        number: number,
        text: text,
        active: isActive
      };
    }
  
    function getPages(currentPage, totalPages) {
      var pages = [];
  
      // Default page limits
      var startPage = 1, endPage = totalPages;
      var isMaxSized = angular.isDefined(maxSize) && maxSize < totalPages;
  
      // recompute if maxSize
      if (isMaxSized) {
        if (rotate) {
          // Current page is displayed in the middle of the visible ones
          startPage = Math.max(currentPage - Math.floor(maxSize / 2), 1);
          endPage = startPage + maxSize - 1;
  
          // Adjust if limit is exceeded
          if (endPage > totalPages) {
            endPage = totalPages;
            startPage = endPage - maxSize + 1;
          }
        } else {
          // Visible pages are paginated with maxSize
          startPage = (Math.ceil(currentPage / maxSize) - 1) * maxSize + 1;
  
          // Adjust last page if limit is exceeded
          endPage = Math.min(startPage + maxSize - 1, totalPages);
        }
      }
  
      // Add page number links
      for (var number = startPage; number <= endPage; number++) {
        var page = makePage(number, number, number === currentPage);
        pages.push(page);
      }
  
      // Add links to move between page sets
      if (isMaxSized && maxSize > 0 && (!rotate || forceEllipses || boundaryLinkNumbers)) {
        if (startPage > 1) {
          if (!boundaryLinkNumbers || startPage > 3) { //need ellipsis for all options unless range is too close to beginning
          var previousPageSet = makePage(startPage - 1, '...', false);
          pages.unshift(previousPageSet);
        }
          if (boundaryLinkNumbers) {
            if (startPage === 3) { //need to replace ellipsis when the buttons would be sequential
              var secondPageLink = makePage(2, '2', false);
              pages.unshift(secondPageLink);
            }
            //add the first page
            var firstPageLink = makePage(1, '1', false);
            pages.unshift(firstPageLink);
          }
        }
  
        if (endPage < totalPages) {
          if (!boundaryLinkNumbers || endPage < totalPages - 2) { //need ellipsis for all options unless range is too close to end
          var nextPageSet = makePage(endPage + 1, '...', false);
          pages.push(nextPageSet);
        }
          if (boundaryLinkNumbers) {
            if (endPage === totalPages - 2) { //need to replace ellipsis when the buttons would be sequential
              var secondToLastPageLink = makePage(totalPages - 1, totalPages - 1, false);
              pages.push(secondToLastPageLink);
            }
            //add the last page
            var lastPageLink = makePage(totalPages, totalPages, false);
            pages.push(lastPageLink);
          }
        }
      }
      return pages;
    }
  
    var originalRender = this.render;
    this.render = function() {
      originalRender();
      if ($scope.page > 0 && $scope.page <= $scope.totalPages) {
        $scope.pages = getPages($scope.page, $scope.totalPages);
      }
    };
  }])
  
  .constant('uibPaginationConfig', {
    itemsPerPage: 10,
    boundaryLinks: false,
    boundaryLinkNumbers: false,
    directionLinks: true,
    firstText: 'First',
    previousText: 'Previous',
    nextText: 'Next',
    lastText: 'Last',
    rotate: true,
    forceEllipses: false
  })
  
  .directive('uibPagination', ['$parse', 'uibPaginationConfig', function($parse, uibPaginationConfig) {
    return {
      scope: {
        totalItems: '=',
        firstText: '@',
        previousText: '@',
        nextText: '@',
        lastText: '@',
        ngDisabled:'='
      },
      require: ['uibPagination', '?ngModel'],
      controller: 'UibPaginationController',
      controllerAs: 'pagination',
      templateUrl: function(element, attrs) {
        return attrs.templateUrl || 'uib/template/pagination/pagination.html';
      },
      replace: true,
      link: function(scope, element, attrs, ctrls) {
        var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1];
  
        if (!ngModelCtrl) {
           return; // do nothing if no ng-model
        }
  
        paginationCtrl.init(ngModelCtrl, uibPaginationConfig);
      }
    };
  }]);
  