#-*- coding: utf-8 -*-
from django.db.models.query import QuerySet
from django.core.paginator import Paginator as CorePaginator
DOT = '...'
ON_EACH_SIDE = 3
ON_ENDS = 2

class IvyPaginator(CorePaginator):
    '''
    view:
    index = getPageNum(request.GET.get('page', 1))
#    g = Group.objects.all().order_by('-responsenums').extra(select={'responsenums': 'select count(*) from group_stuff where group_id = group_group.id'})
    objs = Model.objects.get_object_list(number=index,
        per_page=per_page or 15
        order_by=None
        
        filter.. args
    )
    
    pager = pagination.IvyPaginator(objs, 10, current_page_num=index)
    page = pager.page(index)
    objs = page.object_list

    templates：
    {% for i in pager.page_range %}
    {% ifequal i pager.current_page_num %}
    <span class="this-page">{{ i }} </span>
    {% else %}{% ifequal i '...' %}...{% else %}<a href="?page={{ i }}">{{ i }}</a>{% endifequal %}{% endifequal %}
    {% endfor %}&nbsp;&nbsp;共{{ pager.count }}条记录
    '''
    def __init__(self, _object_list, per_page, orphans=0, allow_empty_first_page=True, current_page_num=1):
        self._ormcache_count = None
        
        if not isinstance(_object_list, QuerySet) and len(_object_list) == 2:
            self._ormcache_count, object_list = _object_list
            
            if not ( isinstance(self._ormcache_count, int) and isinstance(object_list, QuerySet) ):
                self._ormcache_count = None
                object_list = _object_list
        else:
            object_list = _object_list

        CorePaginator.__init__(self, object_list, per_page, orphans=orphans, allow_empty_first_page=allow_empty_first_page)
        self.current_page_num = current_page_num
        
    def page(self, number):
        "Returns a Page object for the given 1-based page number."
        if self._ormcache_count:
            
            return Page(self.object_list, number, self)
        return super(self.__class__, self).page(number)

    def _get_count(self):
        "Returns the total number of objects, across all pages."
        if self._count is None:
            if self._ormcache_count and isinstance( self._ormcache_count, int):
                self._count = self._ormcache_count
            else:
                self._count = len(self.object_list)
        return self._count
    count = property(_get_count)
        
    def _get_page_range(self):
        '''return the page range, simarly like [1,2,3, ..., 98,99,100]'''
        page_range = []
        if self.num_pages <= 10:
            page_range = range(1, self.num_pages+1)
        else:
            if self.current_page_num > (ON_EACH_SIDE + ON_ENDS):
                page_range.extend(range(1, ON_EACH_SIDE + 1))
                page_range.append(DOT)
                page_range.extend(range(self.current_page_num - ON_EACH_SIDE, self.current_page_num + 1))
            else:
                page_range.extend(range(1, self.current_page_num + 1))

            if self.current_page_num < (self.num_pages - ON_EACH_SIDE - ON_ENDS - 1):
                page_range.extend(range(self.current_page_num + 1, self.current_page_num + ON_EACH_SIDE + 1))
                page_range.append(DOT)
                page_range.extend(range(self.num_pages - ON_ENDS, self.num_pages+1))
            else:
                page_range.extend(range(self.current_page_num + 1, self.num_pages+1))
        return page_range
    page_range = property(_get_page_range)

from utils import sql
from django.core.paginator import Page


class IvySqlPaginator(IvyPaginator):
    '''based on sql'''
    def __init__(self, per_page, orphans=0, allow_empty_first_page=True, current_page_num=1, num_pages_sql='', object_list_sql=''):
        CorePaginator.__init__(self, None, per_page, orphans=orphans, allow_empty_first_page=allow_empty_first_page)
        self.current_page_num = current_page_num
        self.num_pages_sql = num_pages_sql
        object_list_sql = object_list_sql.replace('#per_page#', str(per_page) )
        object_list_sql = object_list_sql.replace('#page_start#', str( (current_page_num-1) * per_page ) )
        self.object_list_sql = object_list_sql
        self.object_list = self._get_objs()

    def _get_objs(self):
        _object_list = sql.fetch_dicts(self.object_list_sql)
        return _object_list

    def page(self, number):
        "Returns a Page object for the given 1-based page number."
        number = self.validate_number(number)
        return Page(self.object_list, number, self)

    def _get_count(self):
        "Returns the total number of objects, across all pages."
        if self._count is None:
            c = sql.fetch_dict(self.num_pages_sql)
            self._count = c['c']
            
        return self._count
    count = property(_get_count)
