import numpy as np
from imageio.v2 import imread, imwrite
from numpy.typing import NDArray


def show_red(image: NDArray[np.uint8]) -> NDArray[np.uint8]:
    '''
    Requires: image is a 3D array representing an actual image.
    Modifies: Nothing
    Effects:  Returns the image with the red channel isolated.
    '''
    # TODO: Implement function and return transformed image
    return np.zeros((image.shape[0], image.shape[1], 3), dtype=np.uint8)


def show_green(image: NDArray[np.uint8]) -> NDArray[np.uint8]:
    '''
    Requires: image is a 3D array representing an actual image.
    Modifies: Nothing
    Effects:  Returns the image with the green channel isolated.
    '''
    return np.zeros((image.shape[0], image.shape[1], 3), dtype=np.uint8)


def show_blue(image: NDArray[np.uint8]) -> NDArray[np.uint8]:
    '''
    Requires: image is a 3D array representing an actual image.
    Modifies: Nothing
    Effects:  Returns the image with the blue channel isolated.
    '''
    # TODO: Implement function and return transformed image
    return np.zeros((image.shape[0], image.shape[1], 3), dtype=np.uint8)


def to_grayscale(image: NDArray[np.float64]) -> NDArray[np.uint8]:
    '''
    Requires: image is a 3D array representing an actual image
    Modifies: image
    Effects:  Converts image to grayscale by taking the mean of the
              color intensities across all three channels
              Returns a 2D array representing the grayscale image.
    '''
    # TODO: Implement function and return transformed image
    return np.zeros((image.shape[0], image.shape[1], 3), dtype=np.uint8)


def image_negative(image: NDArray[np.uint8]) -> NDArray[np.uint8]:
    '''
    Requires: image is a 3D array representing an actual image
    Modifies: image
    Effects:  Returns the negative of the image by flipping pixel
              intensities
    '''
    # TODO: Implement function and return transformed image
    return np.zeros((image.shape[0], image.shape[1], 3), dtype=np.uint8)


def adjust_brightness(
        image: NDArray[np.uint8],
        brightness: int = 0
) -> NDArray[np.uint8]:
    '''
    Requires: image is a 3D array representing an actual image
    Modifies: image
    Effects:  Adjusts the brightness of the image by increasing
              or decreasing the intensities of all the color channels,
              ensuring that intensities remain between 0 and 255 even
              after transformation
    '''
    # TODO: Implement function and return transformed image
    return np.zeros((image.shape[0], image.shape[1], 3), dtype=np.uint8)


def blend_images(
        image1: NDArray[np.uint8],
        image2: NDArray[np.uint8],
        alpha: float = 0.5
) -> NDArray[np.uint8]:
    '''
    Requires: image is a 3D array representing an actual image. Alpha is a
    float value in the range [0, 1]
    Modifies: image
    Effects:  Blends the two images, using the alpha value to represent
              what percentage of each image will appear in the final result.
    '''
    # TODO: Implement function and return transformed image
    return np.zeros((image1.shape[0], image1.shape[1], 3), dtype=np.uint8)


# ------- DO NOT CHANGE MAIN ------------------------------
def main() -> None:
    img: NDArray[np.uint8] = imread("example.jpg")
    blend1: NDArray[np.uint8] = imread("blend1.jpg")
    blend2: NDArray[np.uint8] = imread("blend2.jpg")

    print("Running show_red()")
    red = show_red(img)
    imwrite("red.jpg", red)

    print("Running show_green()")
    green = show_green(img)
    imwrite("green.jpg", green)

    print("Running show_blue()")
    blue = show_blue(img)
    imwrite("blue.jpg", blue)

    print("Running to_grayscale()")
    gray = to_grayscale(img)
    imwrite("grayscale.jpg", gray)

    print("Running image_negative()")
    negative = image_negative(img)
    imwrite("negative.jpg", negative)

    print("Running adjust_brightness()")
    contrast = adjust_brightness(img, 50)
    imwrite("brightness.jpg", contrast)

    print("Running blend_images()")
    blend = blend_images(blend1, blend2)
    imwrite("blend.jpg", blend)


if __name__ == '__main__':
    main()
# ----------------------------------------------------------

