import base64
import hashlib
import json


class InvalidPageRequest(Exception):
    pass


class Pager:
    def __init__(self, page_token, page_size, filter_=''):
        if page_size <= 0:
            raise InvalidPageRequest("Page size should be positive.")
        self.filter_hash = _get_hash(filter_ or '')
        self.page_token = page_token or ''
        first_page = not page_token
        if first_page:
            self._offset = 0
        else:
            self._offset, filter_hash = self._parse_next_page_token()
            if filter_hash != self.filter_hash:
                raise InvalidPageRequest('following page request should has the same filter')
        self._page_size = page_size
        self._shift = None

    @property
    def offset(self):
        return self._offset

    @property
    def page_size(self):
        return self._page_size

    def _parse_next_page_token(self):
        decoded = base64.decodebytes(self.page_token.encode('utf-8'))
        return json.loads(decoded.decode('utf-8'))

    def set_shift(self, shift):
        assert shift >= 0
        assert shift <= self.page_size
        self._shift = shift

    @property
    def next_page_token(self):
        assert self._shift is not None
        if self._shift < self.page_size:
            return ''
        raw = json.dumps((self.offset + self._shift, self.filter_hash))
        encoded = base64.encodebytes(raw.encode('utf-8'))
        return encoded.decode('utf-8')


def _get_hash(string: str):
    return hashlib.sha1(string.encode('utf-8')).hexdigest()
