/**
 * dirPagination - AngularJS module for paginating (almost) anything.
 * https://github.com/michaelbromley/angularUtils
 *
 *
 * Credits
 * =======
 *
 * Daniel Tabuenca:
 * https://groups.google.com/d/msg/angular/an9QpzqIYiM/r8v-3W1X5vcJ for the idea
 * on how to dynamically invoke the ng-repeat directive.
 *
 * I borrowed a couple of lines and a few attribute names from the AngularUI
 * Bootstrap project:
 * https://github.com/angular-ui/bootstrap/blob/master/src/pagination/pagination.js
 *
 * Copyright 2014 Michael Bromley <michael@michaelbromley.co.uk>
 */

(function() {

/**
 * Config
 */
var moduleName = 'app.common.directives.dirPagination';
var DEFAULT_ID = '__default';

/**
 * Module
 */
angular.module(moduleName, [])
    .directive(
        'dirPaginate',
        ['$compile', '$parse', 'paginationService', dirPaginateDirective])
    .directive('dirPaginateNoCompile', noCompileDirective)
    .directive(
        'dirPaginationControls',
        [
          'paginationService', 'paginationTemplate',
          dirPaginationControlsDirective
        ])
    .filter('itemsPerPage', ['paginationService', itemsPerPageFilter])
    .service('paginationService', paginationService)
    .provider('paginationTemplate', paginationTemplateProvider)
    .run(['$templateCache', dirPaginationControlsTemplateInstaller]);

function dirPaginateDirective($compile, $parse, paginationService) {
  return {
    terminal: true,
    multiElement: true,
    priority: 100,
    compile: dirPaginationCompileFn
  };

  function dirPaginationCompileFn(tElement, tAttrs) {
    var expression = tAttrs.dirPaginate;
    // regex taken directly from
    // https://github.com/angular/angular.js/blob/v1.4.x/src/ng/directive/ngRepeat.js#L339
    var match = expression.match(
        /^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);

    var filterPattern =
        /\|\s*itemsPerPage\s*:\s*(.*\(\s*\w*\)|([^\)]*?(?=\s+as\s+))|[^\)]*)/;
    if (match[2].match(filterPattern) === null) {
      throw 'pagination directive: the \'itemsPerPage\' filter must be set.';
    }
    var itemsPerPageFilterRemoved = match[2].replace(filterPattern, '');
    var collectionGetter = $parse(itemsPerPageFilterRemoved);

    addNoCompileAttributes(tElement);

    // If any value is specified for paginationId, we register the un-evaluated
    // expression at this stage for the benefit of any dir-pagination-controls
    // directives that may be looking for this ID.
    var rawId = tAttrs.paginationId || DEFAULT_ID;
    paginationService.registerInstance(rawId);

    return function dirPaginationLinkFn(scope, element, attrs) {
      // Now that we have access to the `scope` we can interpolate any
      // expression given in the paginationId attribute and potentially register
      // a new ID if it evaluates to a different value than the rawId.
      var paginationId =
          $parse(attrs.paginationId)(scope) || attrs.paginationId || DEFAULT_ID;

      // (TODO: this seems sound, but I'm reverting as many bug reports followed
      // it's introduction in 0.11.0. Needs more investigation.) In case rawId
      // != paginationId we deregister using rawId for the sake of general
      // cleanliness before registering using paginationId
      // paginationService.deregisterInstance(rawId);
      paginationService.registerInstance(paginationId);

      var repeatExpression = getRepeatExpression(expression, paginationId);
      addNgRepeatToElement(element, attrs, repeatExpression);

      removeTemporaryAttributes(element);
      var compiled = $compile(element);

      var currentPageGetter =
          makeCurrentPageGetterFn(scope, attrs, paginationId);
      paginationService.setCurrentPageParser(
          paginationId, currentPageGetter, scope);

      if (typeof attrs.totalItems !== 'undefined') {
        paginationService.setAsyncModeTrue(paginationId);
        scope.$watch(
            function() {
              return $parse(attrs.totalItems)(scope);
            },
            function(result) {
              if (0 <= result) {
                paginationService.setCollectionLength(paginationId, result);
              }
            });
      } else {
        paginationService.setAsyncModeFalse(paginationId);
        scope.$watchCollection(
            function() {
              return collectionGetter(scope);
            },
            function(collection) {
              if (collection) {
                var collectionLength = (collection instanceof Array) ?
                    collection.length :
                    Object.keys(collection).length;
                paginationService.setCollectionLength(
                    paginationId, collectionLength);
              }
            });
      }

      // Delegate to the link function returned by the new compilation of the
      // ng-repeat
      compiled(scope);

      // (TODO: Reverting this due to many bug reports in v 0.11.0. Needs
      // investigation as the principle is sound) When the scope is destroyed,
      // we make sure to remove the reference to it in paginationService so that
      // it can be properly garbage collected scope.$on('$destroy', function
      // destroyDirPagination() {
      //     paginationService.deregisterInstance(paginationId);
      // });
    };
  }

  /**
   * If a pagination id has been specified, we need to check that it is present
   * as the second argument passed to the itemsPerPage filter. If it is not
   * there, we add it and return the modified expression.
   *
   * @param expression
   * @param paginationId
   * @returns {*}
   */
  function getRepeatExpression(expression, paginationId) {
    var repeatExpression,
        idDefinedInFilter =
            !!expression.match(/(\|\s*itemsPerPage\s*:[^|]*:[^|]*)/);

    if (paginationId !== DEFAULT_ID && !idDefinedInFilter) {
      repeatExpression = expression.replace(
          /(\|\s*itemsPerPage\s*:\s*[^|\s]*)/, '$1 : \'' + paginationId + '\'');
    } else {
      repeatExpression = expression;
    }

    return repeatExpression;
  }

  /**
   * Adds the ng-repeat directive to the element. In the case of multi-element
   * (-start, -end) it adds the appropriate multi-element ng-repeat to the first
   * and last element in the range.
   * @param element
   * @param attrs
   * @param repeatExpression
   */
  function addNgRepeatToElement(element, attrs, repeatExpression) {
    if (element[0].hasAttribute('dir-paginate-start') ||
        element[0].hasAttribute('data-dir-paginate-start')) {
      // using multiElement mode (dir-paginate-start, dir-paginate-end)
      attrs.$set('ngRepeatStart', repeatExpression);
      element.eq(element.length - 1).attr('ng-repeat-end', true);
    } else {
      attrs.$set('ngRepeat', repeatExpression);
    }
  }

  /**
   * Adds the dir-paginate-no-compile directive to each element in the tElement
   * range.
   * @param tElement
   */
  function addNoCompileAttributes(tElement) {
    angular.forEach(tElement, function(el) {
      if (el.nodeType === 1) {
        angular.element(el).attr('dir-paginate-no-compile', true);
      }
    });
  }

  /**
   * Removes the variations on dir-paginate (data-, -start, -end) and the
   * dir-paginate-no-compile directives.
   * @param element
   */
  function removeTemporaryAttributes(element) {
    angular.forEach(element, function(el) {
      if (el.nodeType === 1) {
        angular.element(el).removeAttr('dir-paginate-no-compile');
      }
    });
    element.eq(0)
        .removeAttr('dir-paginate-start')
        .removeAttr('dir-paginate')
        .removeAttr('data-dir-paginate-start')
        .removeAttr('data-dir-paginate');
    element.eq(element.length - 1)
        .removeAttr('dir-paginate-end')
        .removeAttr('data-dir-paginate-end');
  }

  /**
   * Creates a getter function for the current-page attribute, using the
   * expression provided or a default value if no current-page expression was
   * specified.
   *
   * @param scope
   * @param attrs
   * @param paginationId
   * @returns {*}
   */
  function makeCurrentPageGetterFn(scope, attrs, paginationId) {
    var currentPageGetter;
    if (attrs.currentPage) {
      currentPageGetter = $parse(attrs.currentPage);
    } else {
      // If the current-page attribute was not set, we'll make our own.
      // Replace any non-alphanumeric characters which might confuse
      // the $parse service and give unexpected results.
      // See https://github.com/michaelbromley/angularUtils/issues/233
      var defaultCurrentPage =
          (paginationId + '__currentPage').replace(/\W/g, '_');
      scope[defaultCurrentPage] = 1;
      currentPageGetter = $parse(defaultCurrentPage);
    }
    return currentPageGetter;
  }
}

/**
 * This is a helper directive that allows correct compilation when in
 * multi-element mode (ie dir-paginate-start, dir-paginate-end). It is
 * dynamically added to all elements in the dir-paginate compile function, and
 * it prevents further compilation of any inner directives. It is then removed
 * in the link function, and all inner directives are then manually compiled.
 */
function noCompileDirective() {
  return {priority: 5000, terminal: true};
}

function dirPaginationControlsTemplateInstaller($templateCache) {
  $templateCache.put(
      'app.common.directives.dirPagination.template',
      '<ul class="pagination" ng-if="1 < pages.length || !autoHide"><li ng-if="boundaryLinks" ng-class="{ disabled : pagination.current == 1 }"><a href="" ng-click="setCurrent(1)">&laquo;</a></li><li ng-if="directionLinks" ng-class="{ disabled : pagination.current == 1 }"><a href="" ng-click="setCurrent(pagination.current - 1)">&lsaquo;</a></li><li ng-repeat="pageNumber in pages track by tracker(pageNumber, $index)" ng-class="{ active : pagination.current == pageNumber, disabled : pageNumber == \'...\' || ( ! autoHide && pages.length === 1 ) }"><a href="" ng-click="setCurrent(pageNumber)">{{ pageNumber }}</a></li><li ng-if="directionLinks" ng-class="{ disabled : pagination.current == pagination.last }"><a href="" ng-click="setCurrent(pagination.current + 1)">&rsaquo;</a></li><li ng-if="boundaryLinks"  ng-class="{ disabled : pagination.current == pagination.last }"><a href="" ng-click="setCurrent(pagination.last)">&raquo;</a></li></ul>');
}

function dirPaginationControlsDirective(paginationService, paginationTemplate) {
  var numberRegex = /^\d+$/;

  var DDO = {
    restrict: 'AE',
    scope:
        {maxSize: '=?', onPageChange: '&?', paginationId: '=?', autoHide: '=?'},
    link: dirPaginationControlsLinkFn
  };

  // We need to check the paginationTemplate service to see whether a template
  // path or string has been specified, and add the `template` or `templateUrl`
  // property to the DDO as appropriate. The order of priority to decide which
  // template to use is (highest priority first):
  // 1. paginationTemplate.getString()
  // 2. attrs.templateUrl
  // 3. paginationTemplate.getPath()
  var templateString = paginationTemplate.getString();
  if (templateString !== undefined) {
    DDO.template = templateString;
  } else {
    DDO.templateUrl = function(elem, attrs) {
      return attrs.templateUrl || paginationTemplate.getPath();
    };
  }
  return DDO;

  function dirPaginationControlsLinkFn(scope, element, attrs) {
    // rawId is the un-interpolated value of the pagination-id attribute. This
    // is only important when the corresponding dir-paginate directive has not
    // yet been linked (e.g. if it is inside an ng-if block), and in that case
    // it prevents this controls directive from assuming that there is no
    // corresponding dir-paginate directive and wrongly throwing an exception.
    var rawId = attrs.paginationId || DEFAULT_ID;
    var paginationId = scope.paginationId || attrs.paginationId || DEFAULT_ID;

    if (!paginationService.isRegistered(paginationId) &&
        !paginationService.isRegistered(rawId)) {
      var idMessage =
          (paginationId !== DEFAULT_ID) ? ' (id: ' + paginationId + ') ' : ' ';
      if (window.console) {
        console.warn(
            'Pagination directive: the pagination controls' + idMessage +
            'cannot be used without the corresponding pagination directive, which was not found at link time.');
      }
    }

    if (!scope.maxSize) {
      scope.maxSize = 9;
    }
    scope.autoHide = scope.autoHide === undefined ? true : scope.autoHide;
    scope.directionLinks = angular.isDefined(attrs.directionLinks) ?
        scope.$parent.$eval(attrs.directionLinks) :
        true;
    scope.boundaryLinks = angular.isDefined(attrs.boundaryLinks) ?
        scope.$parent.$eval(attrs.boundaryLinks) :
        false;

    var paginationRange = Math.max(scope.maxSize, 5);
    scope.pages = [];
    scope.pagination = {last: 1, current: 1};
    scope.range = {lower: 1, upper: 1, total: 1};

    scope.$watch('maxSize', function(val) {
      if (val) {
        paginationRange = Math.max(scope.maxSize, 5);
        generatePagination();
      }
    });

    scope.$watch(
        function() {
          if (paginationService.isRegistered(paginationId)) {
            return (paginationService.getCollectionLength(paginationId) + 1) *
                paginationService.getItemsPerPage(paginationId);
          }
        },
        function(length) {
          if (0 < length) {
            generatePagination();
          }
        });

    scope.$watch(
        function() {
          if (paginationService.isRegistered(paginationId)) {
            return (paginationService.getItemsPerPage(paginationId));
          }
        },
        function(current, previous) {
          if (current != previous && typeof previous !== 'undefined') {
            goToPage(scope.pagination.current);
          }
        });

    scope.$watch(
        function() {
          if (paginationService.isRegistered(paginationId)) {
            return paginationService.getCurrentPage(paginationId);
          }
        },
        function(currentPage, previousPage) {
          if (currentPage != previousPage) {
            goToPage(currentPage);
          }
        });

    scope.setCurrent = function(num) {
      if (paginationService.isRegistered(paginationId) &&
          isValidPageNumber(num)) {
        num = parseInt(num, 10);
        paginationService.setCurrentPage(paginationId, num);
      }
    };

    /**
     * Custom "track by" function which allows for duplicate "..." entries on
     * long lists, yet fixes the problem of wrongly-highlighted links which
     * happens when using "track by $index" - see
     * https://github.com/michaelbromley/angularUtils/issues/153
     * @param id
     * @param index
     * @returns {string}
     */
    scope.tracker = function(id, index) {
      return id + '_' + index;
    };

    function goToPage(num) {
      if (paginationService.isRegistered(paginationId) &&
          isValidPageNumber(num)) {
        var oldPageNumber = scope.pagination.current;

        scope.pages = generatePagesArray(
            num, paginationService.getCollectionLength(paginationId),
            paginationService.getItemsPerPage(paginationId), paginationRange);
        scope.pagination.current = num;
        updateRangeValues();

        // if a callback has been set, then call it with the page number as the
        // first argument and the previous page number as a second argument
        if (scope.onPageChange) {
          scope.onPageChange(
              {newPageNumber: num, oldPageNumber: oldPageNumber});
        }
      }
    }

    function generatePagination() {
      if (paginationService.isRegistered(paginationId)) {
        var page =
            parseInt(paginationService.getCurrentPage(paginationId)) || 1;
        scope.pages = generatePagesArray(
            page, paginationService.getCollectionLength(paginationId),
            paginationService.getItemsPerPage(paginationId), paginationRange);
        scope.pagination.current = page;
        scope.pagination.last = scope.pages[scope.pages.length - 1];
        if (scope.pagination.last < scope.pagination.current) {
          scope.setCurrent(scope.pagination.last);
        } else {
          updateRangeValues();
        }
      }
    }

    /**
     * This function updates the values (lower, upper, total) of the
     * `scope.range` object, which can be used in the pagination template to
     * display the current page range, e.g. "showing 21 - 40 of 144 results";
     */
    function updateRangeValues() {
      if (paginationService.isRegistered(paginationId)) {
        var currentPage = paginationService.getCurrentPage(paginationId),
            itemsPerPage = paginationService.getItemsPerPage(paginationId),
            totalItems = paginationService.getCollectionLength(paginationId);

        scope.range.lower = (currentPage - 1) * itemsPerPage + 1;
        scope.range.upper = Math.min(currentPage * itemsPerPage, totalItems);
        scope.range.total = totalItems;
      }
    }
    function isValidPageNumber(num) {
      return (
          numberRegex.test(num) && (0 < num && num <= scope.pagination.last));
    }
  }

  /**
   * Generate an array of page numbers (or the '...' string) which is used in an
   * ng-repeat to generate the links used in pagination
   *
   * @param currentPage
   * @param rowsPerPage
   * @param paginationRange
   * @param collectionLength
   * @returns {Array}
   */
  function generatePagesArray(
      currentPage, collectionLength, rowsPerPage, paginationRange) {
    var pages = [];
    var totalPages = Math.ceil(collectionLength / rowsPerPage);
    var halfWay = Math.ceil(paginationRange / 2);
    var position;

    if (currentPage <= halfWay) {
      position = 'start';
    } else if (totalPages - halfWay < currentPage) {
      position = 'end';
    } else {
      position = 'middle';
    }

    var ellipsesNeeded = paginationRange < totalPages;
    var i = 1;
    while (i <= totalPages && i <= paginationRange) {
      var pageNumber =
          calculatePageNumber(i, currentPage, paginationRange, totalPages);

      var openingEllipsesNeeded =
          (i === 2 && (position === 'middle' || position === 'end'));
      var closingEllipsesNeeded =
          (i === paginationRange - 1 &&
           (position === 'middle' || position === 'start'));
      if (ellipsesNeeded && (openingEllipsesNeeded || closingEllipsesNeeded)) {
        pages.push('...');
      } else {
        pages.push(pageNumber);
      }
      i++;
    }
    return pages;
  }

  /**
   * Given the position in the sequence of pagination links [i], figure out what
   * page number corresponds to that position.
   *
   * @param i
   * @param currentPage
   * @param paginationRange
   * @param totalPages
   * @returns {*}
   */
  function calculatePageNumber(i, currentPage, paginationRange, totalPages) {
    var halfWay = Math.ceil(paginationRange / 2);
    if (i === paginationRange) {
      return totalPages;
    } else if (i === 1) {
      return i;
    } else if (paginationRange < totalPages) {
      if (totalPages - halfWay < currentPage) {
        return totalPages - paginationRange + i;
      } else if (halfWay < currentPage) {
        return currentPage - halfWay + i;
      } else {
        return i;
      }
    } else {
      return i;
    }
  }
}

/**
 * This filter slices the collection into pages based on the current page number
 * and number of items per page.
 * @param paginationService
 * @returns {Function}
 */
function itemsPerPageFilter(paginationService) {
  return function(collection, itemsPerPage, paginationId) {
    if (typeof (paginationId) === 'undefined') {
      paginationId = DEFAULT_ID;
    }
    if (!paginationService.isRegistered(paginationId)) {
      throw 'pagination directive: the itemsPerPage id argument (id: ' +
          paginationId + ') does not match a registered pagination-id.';
    }
    var end;
    var start;
    if (angular.isObject(collection)) {
      itemsPerPage = parseInt(itemsPerPage) || 9999999999;
      if (paginationService.isAsyncMode(paginationId)) {
        start = 0;
      } else {
        start =
            (paginationService.getCurrentPage(paginationId) - 1) * itemsPerPage;
      }
      end = start + itemsPerPage;
      paginationService.setItemsPerPage(paginationId, itemsPerPage);

      if (collection instanceof Array) {
        // the array just needs to be sliced
        return collection.slice(start, end);
      } else {
        // in the case of an object, we need to get an array of keys, slice
        // that, then map back to the original object.
        var slicedObject = {};
        angular.forEach(keys(collection).slice(start, end), function(key) {
          slicedObject[key] = collection[key];
        });
        return slicedObject;
      }
    } else {
      return collection;
    }
  };
}

/**
 * Shim for the Object.keys() method which does not exist in IE < 9
 * @param obj
 * @returns {Array}
 */
function keys(obj) {
  if (!Object.keys) {
    var objKeys = [];
    for (var i in obj) {
      if (obj.hasOwnProperty(i)) {
        objKeys.push(i);
      }
    }
    return objKeys;
  } else {
    return Object.keys(obj);
  }
}

/**
 * This service allows the various parts of the module to communicate and stay
 * in sync.
 */
function paginationService() {
  var instances = {};
  var lastRegisteredInstance;

  this.registerInstance = function(instanceId) {
    if (typeof instances[instanceId] === 'undefined') {
      instances[instanceId] = {asyncMode: false};
      lastRegisteredInstance = instanceId;
    }
  };

  this.deregisterInstance = function(instanceId) {
    delete instances[instanceId];
  };

  this.isRegistered = function(instanceId) {
    return (typeof instances[instanceId] !== 'undefined');
  };

  this.getLastInstanceId = function() {
    return lastRegisteredInstance;
  };

  this.setCurrentPageParser = function(instanceId, val, scope) {
    instances[instanceId].currentPageParser = val;
    instances[instanceId].context = scope;
  };
  this.setCurrentPage = function(instanceId, val) {
    instances[instanceId].currentPageParser.assign(
        instances[instanceId].context, val);
  };
  this.getCurrentPage = function(instanceId) {
    var parser = instances[instanceId].currentPageParser;
    return parser ? parser(instances[instanceId].context) : 1;
  };

  this.setItemsPerPage = function(instanceId, val) {
    instances[instanceId].itemsPerPage = val;
  };
  this.getItemsPerPage = function(instanceId) {
    return instances[instanceId].itemsPerPage;
  };

  this.setCollectionLength = function(instanceId, val) {
    instances[instanceId].collectionLength = val;
  };
  this.getCollectionLength = function(instanceId) {
    return instances[instanceId].collectionLength;
  };

  this.setAsyncModeTrue = function(instanceId) {
    instances[instanceId].asyncMode = true;
  };

  this.setAsyncModeFalse = function(instanceId) {
    instances[instanceId].asyncMode = false;
  };

  this.isAsyncMode = function(instanceId) {
    return instances[instanceId].asyncMode;
  };
}

/**
 * This provider allows global configuration of the template path used by the
 * dir-pagination-controls directive.
 */
function paginationTemplateProvider() {
  var templatePath = 'app.common.directives.dirPagination.template';
  var templateString;

  /**
   * Set a templateUrl to be used by all instances of <dir-pagination-controls>
   * @param {String} path
   */
  this.setPath = function(path) {
    templatePath = path;
  };

  /**
   * Set a string of HTML to be used as a template by all instances
   * of <dir-pagination-controls>. If both a path *and* a string have been set,
   * the string takes precedence.
   * @param {String} str
   */
  this.setString = function(str) {
    templateString = str;
  };

  this.$get = function() {
    return {
      getPath: function() {
        return templatePath;
      },
      getString: function() {
        return templateString;
      }
    };
  };
}
})();
