from typing import List, Tuple, Dict

"""
Framebuffer's top level array contains all rows which contains all the pixels.
All the pixels are triplets of 8-bit RGB (Truecolour).
"""
FrameBuffer = List[List[Tuple[int]]]

class ImageGenerator():
    """
    This class generates an image, and works as source of infinite image
    frames. The pixelformats used is Truecolour (8-bit RGB`), alpha information
    is not supported. It doesn't generate pixels itself, instead it expects
    the user to create function that generates pixels to filled inside a framebuffer.

    For example this is a sample usage of this program, this generates blank black RGB
    frames, with size of "Full HD" (1920×1080).
    ```
    i = ImageGenerator(-1920, 1080)
    i.generate(lambda x,y,w,h: (0, 0, 0))
    ```
    
    Tip: the `_frame` property contains the fresh rendered frame, this is useful if
    you want to reuse the frame again and again.
    """
    def __init__(self, width, height):
        self.width = abs(width)
        self.height = abs(height)

        # Framebuffer storage to store pixel data per frame.
        self._frame: FrameBuffer = [[] * width] * height

    def generate(self, pixelGenerator) -> FrameBuffer:
        """
        Generates image frame of RGB pixels by calling a function
        which repeatedly generates triplets of RGB wrapped inside
        a tuple. These triplets are combined to create a full-frame
        and the frame is returned as the result.

        `pixelGenerator` —
            Callback function which returns a triplet of RGB,
            wrapped inside a tuple.
            This method is called on each iteration.
        """

        # Iterate over all rows and columns, and call the function
        # again and again to get pixels.
        for y in range(self.height):
            for x in range(self.width):
                self._frame[x][y] = pixelGenerator(x, y, self.width, self.height)

        return self._frame