import requests
import cv2 as cv
import numpy as np


class IIIFComponent:
    """
    Base class for all IIIF components
    """

    def __init__(self, url: str):
        self.url = url
        self._data = None

    @property
    def data(self):
        if not self._data:
            self._data = requests.get(self.url).json()
        return self._data

    @property
    def id(self):
        return self.data['@id']

    @property
    def context(self):
        return self.data['@context']

    @property
    def type(self):
        return self.data['@type']


class IIIFImage(IIIFComponent):
    def load_image(self, region: str = 'full', size: str = 'full', rotation:
    int = 0, quality: str = 'default', format: str = 'jpg'):
        image_url = f"{self.id}/{region}/{size}" \
                    f"/{rotation}" \
                    f"/{quality}" \
                    f".{format}"
        image_request = requests.get(image_url, stream=True)
        image = np.asarray(bytearray(image_request.raw.read()), dtype='uint8')
        image = cv.imdecode(image, cv.IMREAD_COLOR)
        return image


class IIIFManifest(IIIFComponent):
    """
    A class for handling IIIF manifests for further processing.
    """

    def get_images(self, indices: list = [], sequence_number: int = 0):
        # return all images if empty list
        if len(indices) == 0:
            indices = range(len(self.data['sequences'][sequence_number][
                                    'canvases']))
        for i in indices:
            for image in self.data['sequences'][sequence_number]['canvases'][
                i]['images']:
                yield IIIFImage(image['resource']['service']['@id'])
