/*
  backbone-pageable 1.2.3
  http://github.com/wyuenho/backbone-pageable

  Copyright (c) 2013 Jimmy Yuen Ho Wong
  Licensed under the MIT @license.
*/
(function(e){if("object"==typeof exports)module.exports=e(require("underscore"),require("backbone"));else if("function"==typeof define&&define.amd)define(["underscore","backbone"],e);else if("undefined"!=typeof _&&"undefined"!=typeof Backbone){var t=Backbone.PageableCollection,r=Backbone.PageableCollection=e(_,Backbone);Backbone.PageableCollection.noConflict=function(){return Backbone.PageableCollection=t,r}}})(function(e,t){"use strict";function r(t,r){if(!e.isNumber(t)||e.isNaN(t)||!e.isFinite(t)||~~t!==t)throw new TypeError("`"+r+"` must be a finite integer");return t}function a(e){for(var t,r,a,s,i={},n=decodeURIComponent,o=e.split("&"),l=0,c=o.length;c>l;l++){var u=o[l];t=u.split("="),r=t[0],a=t[1]||!0,r=n(r),s=i[r],d(s)?s.push(a):i[r]=s?[s,a]:a}return i}function s(){var t=arguments[0],r=e.toArray(arguments).slice(1),a=t.comparator;t.comparator=null;try{t.reset.apply(t,r)}finally{t.comparator=a,a&&t.sort()}return t}var i=e.extend,n=e.omit,o=e.clone,l=e.each,c=e.pick,u=e.contains,h=e.isEmpty,f=e.pairs,g=e.invert,d=e.isArray,p=e.isFunction,v=e.isObject,P=e.keys,m=e.isUndefined,y=e.result,k=Math.ceil,b=Math.floor,S=Math.max,_=t.Collection.prototype,C=/[\s'"]/g,R=/[<>\s'"]/g,x=t.Collection.extend({state:{firstPage:1,lastPage:null,currentPage:null,pageSize:25,totalPages:null,totalRecords:null,sortKey:null,order:-1},mode:"server",queryParams:{currentPage:"page",pageSize:"per_page",totalPages:"total_pages",totalRecords:"total_entries",sortKey:"sort_by",order:"order",directions:{"-1":"asc",1:"desc"}},initialize:function(e,t){t=t||{};var r=this.mode=t.mode||this.mode||w.mode,a=i({},w.queryParams,this.queryParams,t.queryParams||{});a.directions=i({},w.queryParams.directions,this.queryParams.directions,a.directions||{}),this.queryParams=a;var s=this.state=i({},w.state,this.state,t.state||{});s.currentPage=s.currentPage==null?s.firstPage:s.currentPage,d(e)||(e=e?[e]:[]),"server"==r||s.totalRecords!=null||h(e)||(s.totalRecords=e.length),this.switchMode(r,i({fetch:!1,resetState:!1,models:e},t));var n=t.comparator;if(s.sortKey&&!n&&this.setSorting(s.sortKey,s.order,t),"server"!=r){if(n&&t.full){delete this.comparator;var l=this.fullCollection;l.comparator=n,l.sort()}e&&!h(e)&&(this.getPage(s.currentPage),e.splice.apply(e,[0,e.length].concat(this.models)))}this._initState=o(this.state)},_makeFullCollection:function(e,r){var a,s,i,n=["url","model","sync","comparator"],o=this.constructor.prototype,l={};for(a=0,s=n.length;s>a;a++)i=n[a],m(o[i])||(l[i]=o[i]);var c=new(t.Collection.extend(l))(e,r);for(a=0,s=n.length;s>a;a++)i=n[a],this[i]!==o[i]&&(c[i]=this[i]);return c},_makeCollectionEventHandler:function(e,t){return function(r,a,n,c){var u=e._handlers;l(P(u),function(r){var a=u[r];e.off(r,a),t.off(r,a)});var h=o(e.state),f=h.firstPage,g=0===f?h.currentPage:h.currentPage-1,d=h.pageSize,p=g*d,v=p+d;if("add"==r){var y,b,S,_,c=c||{};if(n==t)b=t.indexOf(a),b>=p&&v>b&&(_=e,y=S=b-p);else{y=e.indexOf(a),b=p+y,_=t;var S=m(c.at)?b:c.at+p}if(++h.totalRecords,e.state=e._checkState(h),_){_.add(a,i({},c||{},{at:S}));var C=y>=d?a:!m(c.at)&&v>S&&e.length>d?e.at(d):null;if(C){var R=n._events.add||[],x={onAdd:!0};if(R.length){var w=R[R.length-1],q=w.callback;w.callback=function(){try{q.apply(this,arguments),e.remove(C,x)}finally{w.callback=q}}}else e.remove(C,x)}}}if("remove"==r)if(c.onAdd)delete c.onAdd;else{if(--h.totalRecords){var z=h.totalPages=k(h.totalRecords/d);h.lastPage=0===f?z-1:z,h.currentPage>z&&(h.currentPage=h.lastPage)}else h.totalRecords=null,h.totalPages=null;e.state=e._checkState(h);var E,K=c.index;n==e?((E=t.at(v))&&e.push(E),t.remove(a)):K>=p&&v>K&&(e.remove(a),E=t.at(g*(d+K)),E&&e.push(E))}if("reset"==r||"sort"==r){if(c=n,n=a,n==e&&"reset"==r){var B=t.models.slice(0,p),N=t.models.slice(p+e.models.length);c=i(c,{silent:!0}),s(t,B.concat(e.models).concat(N),c)}("reset"==r||n==t)&&((h.totalRecords=t.models.length)||(h.totalRecords=null,h.totalPages=null,h.lastPage=h.currentPage=h.firstPage),e.state=e._checkState(h),n==e&&t.trigger(r,t,c),s(e,t.models.slice(p,v),i({},c,{parse:!1})))}l(P(u),function(r){var a=u[r];l([e,t],function(e){e.on(r,a);var t=e._events[r]||[];t.unshift(t.pop())})})}},_checkState:function(e){var t=this.mode,a=this.links,s=e.totalRecords,i=e.pageSize,n=e.currentPage,o=e.firstPage,l=e.totalPages;if(null!=s&&null!=i&&null!=n&&null!=o&&("infinite"==t?a:!0)){if(s=r(s,"totalRecords"),i=r(i,"pageSize"),n=r(n,"currentPage"),o=r(o,"firstPage"),1>i)throw new RangeError("`pageSize` must be >= 1");if(l=e.totalPages=k(s/i),0>o||o>1)throw new RangeError("`firstPage must be 0 or 1`");if(e.lastPage=0===o?S(0,l-1):l,"infinite"==t){if(!a[n+""])throw new RangeError("No link found for page "+n)}else if(o>n||l>0&&(o?n>l:n>=l))throw new RangeError("`currentPage` must be firstPage <= currentPage "+(o?">":">=")+" totalPages if "+o+"-based. Got "+n+".")}return e},setPageSize:function(e,t){return e=r(e,"pageSize"),t=t||{},this.state=this._checkState(i({},this.state,{pageSize:e,totalPages:k(this.state.totalRecords/e)})),this.getPage(this.state.currentPage,t)},switchMode:function(t,r){if(!u(["server","client","infinite"],t))throw new TypeError('`mode` must be one of "server", "client" or "infinite"');r=r||{fetch:!0,resetState:!0};var a=this.state=r.resetState?o(this._initState):this._checkState(i({},this.state));this.mode=t;var s,c=this,h=this.fullCollection,f=this._handlers=this._handlers||{};if("server"==t||h)"server"==t&&h&&(l(P(f),function(e){s=f[e],c.off(e,s),h.off(e,s)}),delete this._handlers,this._fullComparator=h.comparator,delete this.fullCollection);else{h=this._makeFullCollection(r.models||[]),h.pageableCollection=this,this.fullCollection=h;var g=this._makeCollectionEventHandler(this,h);l(["add","remove","reset","sort"],function(t){f[t]=s=e.bind(g,{},t),c.on(t,s),h.on(t,s)}),h.comparator=this._fullComparator}if("infinite"==t)for(var d=this.links={},p=a.firstPage,v=k(a.totalRecords/a.pageSize),m=0===p?S(0,v-1):v||p,y=a.firstPage;m>=y;y++)d[y]=this.url;else this.links&&delete this.links;return r.fetch?this.fetch(n(r,"fetch","resetState")):this},hasPrevious:function(){var e=this.state,t=e.currentPage;return this.mode!="infinite"?t>e.firstPage:!!this.links[t-1]},hasNext:function(){var e=this.state,t=this.state.currentPage;return this.mode!="infinite"?t<e.lastPage:!!this.links[t+1]},getFirstPage:function(e){return this.getPage("first",e)},getPreviousPage:function(e){return this.getPage("prev",e)},getNextPage:function(e){return this.getPage("next",e)},getLastPage:function(e){return this.getPage("last",e)},getPage:function(e,t){var a=this.mode,o=this.fullCollection;t=t||{fetch:!1};var l=this.state,c=l.firstPage,u=l.currentPage,f=l.lastPage,g=l.pageSize,d=e;switch(e){case"first":d=c;break;case"prev":d=u-1;break;case"next":d=u+1;break;case"last":d=f;break;default:d=r(e,"index")}this.state=this._checkState(i({},l,{currentPage:d}));var p=(0===c?d:d-1)*g,v=o&&o.length?o.models.slice(p,p+g):[];return"client"!=a&&("infinite"!=a||h(v))||t.fetch?("infinite"==a&&(t.url=this.links[d]),this.fetch(n(t,"fetch"))):s(this,v,n(t,"fetch"))},getPageByOffset:function(e,t){if(0>e)throw new RangeError("`offset must be > 0`");e=r(e);var a=b(e/this.state.pageSize);return this.state.firstPage!==0&&a++,a>this.state.lastPage&&(a=this.state.lastPage),this.getPage(a,t)},sync:function(e,r,a){var s=this;if(s.mode=="infinite"){var n=a.success,o=s.state.currentPage;a.success=function(e,t,r){var l=s.links,c=s.parseLinks(e,i({xhr:r},a));c.first&&(l[s.state.firstPage]=c.first),c.prev&&(l[o-1]=c.prev),c.next&&(l[o+1]=c.next),n&&n(e,t,r)}}return(_.sync||t.sync).call(s,e,r,a)},parseLinks:function(e,t){var r={},s=t.xhr.getResponseHeader("Link");if(s){var i=["first","prev","previous","next","last"];l(s.split(","),function(e){var t=e.split(";"),a=t[0].replace(R,""),s=t.slice(1);l(s,function(e){var t=e.split("="),s=t[0].replace(C,""),n=t[1].replace(C,"");"rel"==s&&u(i,n)&&("previous"==n?r.prev=a:r[n]=a)})});var n,c,h=r.last||"";if(c=(n=h.indexOf("?"))?h.slice(n+1):""){var f=a(c),g=o(this.state),d=this.queryParams,p=g.pageSize,v=f[d.totalRecords]*1,P=f[d.currentPage]*1,m=f[d.totalPages];v||(P?v=(g.firstPage===0?P+1:P)*p:m&&(v=m*p)),v&&(g.totalRecords=v),this.state=this._checkState(g)}}return delete r.last,r},parse:function(e){var t=this.parseState(e,o(this.queryParams),o(this.state));return t&&(this.state=this._checkState(i({},this.state,t))),this.parseRecords(e)},parseState:function(t,r,a){if(t&&t.length===2&&v(t[0])&&d(t[1])){var s=o(a),i=t[0];return l(f(n(r,"directions")),function(t){var r=t[0],a=t[1],n=i[a];m(n)||e.isNull(n)||(s[r]=i[a])}),i.order&&(s.order=g(r.directions)[i.order]*1),s}},parseRecords:function(e){return e&&e.length===2&&v(e[0])&&d(e[1])?e[1]:e},fetch:function(e){e=e||{};var t=this._checkState(this.state),r=this.mode;"infinite"!=r||e.url||(e.url=this.links[t.currentPage]);var l=e.data||{},u=y(e,"url")||y(this,"url")||"",h=u.indexOf("?");-1!=h&&(i(l,a(u.slice(h+1))),u=u.slice(0,h)),e.url=u,e.data=l;var g,d,v,k,b=this.mode=="client"?c(this.queryParams,"sortKey","order"):n(c(this.queryParams,P(w.queryParams)),"directions"),S=f(b),C=o(this);for(g=0;g<S.length;g++)d=S[g],v=d[0],k=d[1],k=p(k)?k.call(C):k,t[v]!=null&&null!=k&&(l[k]=t[v]);t.sortKey&&t.order?l[b.order]=this.queryParams.directions[t.order+""]:t.sortKey||delete l[b.order];var R=f(n(this.queryParams,P(w.queryParams)));for(g=0;g<R.length;g++)d=R[g],k=d[1],k=p(k)?k.call(C):k,l[d[0]]=k;var x=this.fullCollection,q=this.links;if("server"!=r){var z=this,E=e.success;return e.success=function(a,n,o){o=o||{},m(e.silent)?delete o.silent:o.silent=e.silent;var l=a.models,c=t.currentPage;if("client"==r)s(x,l,o);else if(q[c]){var u=t.pageSize,h=(t.firstPage===0?c:c-1)*u,f=x.models,g=f.slice(0,h),d=f.slice(h+u);f=g.concat(l).concat(d);var p=x.set||x.update;p.call(x,f,i({silent:!0,sort:!1},o)),x.comparator&&x.sort(),x.trigger("reset",x,o)}else x.add(l,i({at:x.length,silent:!0},o)),x.trigger("reset",x,o);E&&E(a,n,o)},_.fetch.call(z,i({},e,{silent:!0}))}return _.fetch.call(this,e)},_makeComparator:function(e,t){var r=this.state;return e=e||r.sortKey,t=t||r.order,e&&t?function(r,a){var s,i=r.get(e),n=a.get(e);return 1===t&&(s=i,i=n,n=s),i===n?0:n>i?-1:1}:void 0},setSorting:function(e,t,r){var a=this.state;a.sortKey=e,a.order=t=t||a.order;var s=this.fullCollection,n=!1,o=!1;e||(n=o=!0);var l=this.mode;r=i({side:"client"==l?l:"server",full:!0},r);var c=this._makeComparator(e,t),u=r.full,h=r.side;return"client"==h?u?(s&&(s.comparator=c),n=!0):(this.comparator=c,o=!0):"server"!=h||u||(this.comparator=c),n&&delete this.comparator,o&&s&&delete s.comparator,this}}),w=x.prototype;return x});