from django.core.paginator import EmptyPage, InvalidPage


def get_page(queryset, order_by, per_page, start=0):
    if start < 0:
        raise InvalidPage()

    object_list = list(_slice_queryset(queryset, order_by, per_page, start))
    if start and not object_list:
        raise EmptyPage()

    next_cursor = None
    if len(object_list) > per_page:
        next_slice_first_item = object_list.pop(-1)
        attr_name = order_by.lstrip("-")
        next_cursor = getattr(next_slice_first_item, attr_name)

    return CursorPage(start, object_list, next_cursor)


def _slice_queryset(queryset, order_by, per_page, start):
    page_len = int(per_page) + 1
    if start:
        if order_by.startswith("-"):
            filter_name = "%s__lte" % order_by[1:]
        else:
            filter_name = "%s__gte" % order_by
        return queryset.filter(**{filter_name: start})[:page_len]
    return queryset[:page_len]


class CursorPage:
    def __init__(self, start, object_list, next_=None):
        self.start = start or 0
        self.first = self.start == 0
        self.object_list = object_list
        self.next = next_

    def __len__(self):
        return len(self.object_list)

    def has_next(self):
        return bool(self.next)