import numpy
import warnings

from discrete_fuzzy_operators.base.operators.binary_operators.suboperators.fuzzy_implication_operator import \
    DiscreteFuzzyImplicationOperator
from discrete_fuzzy_morphology.base.structuring_element import StructuringElement


def fuzzy_image_erosion(image: numpy.ndarray,
                        structuring_element: StructuringElement,
                        iterations: int,
                        implication: DiscreteFuzzyImplicationOperator) -> numpy.ndarray:
    """
    Applies the fuzzy erosion to a grayscale image.

    Args:
        image: A numpy array, representing the image to be eroded.
        structuring_element: A StructuringElement object, representing the properties and the shape of the
                             structuring element to be used.
        iterations: An integer, representing the number of times that the erosion has to be applied to the image.
        implication: A DiscreteFuzzyImplicationOperator object, representing the implication to be used.

    References:
        <NAME>., & <NAME>. (2014).
        A fuzzy mathematical morphology based on discrete t-norms: fundamentals and applications to image processing.
        Soft Computing, 18 (11), 2297–2311. https://doi.org/10.1007/s00500-013-1204-6

    Returns:
        An image with the same dimension as the input image, representing the eroded image.
    """
    if not implication.is_implication():
        warnings.warn("The selected operator is not a fuzzy implication function. Results may not be correct.")

    img_rows, img_columns = image.shape
    se_rows, se_columns = structuring_element.dimension

    erosion_result = image.copy()

    iteration = image.copy()
    for _ in range(0, iterations):

        for i in range(0, img_rows):
            for j in range(0, img_columns):
                min_value = 255

                for ii in range(0, se_rows):
                    for jj in range(0, se_columns):
                        try:
                            x_value = structuring_element.evaluate(x=jj, y=ii)
                            y_value = iteration[i+ii-structuring_element.center[0], j+jj-structuring_element.center[1]]

                            implication_value = implication.evaluate_operator(x=x_value, y=y_value)

                            if implication_value < min_value:
                                min_value = implication_value
                        except:
                            continue
                erosion_result[i, j] = min_value
        iteration = erosion_result.copy()

    return erosion_result


import numpy
import warnings

from discrete_fuzzy_operators.base.operators.binary_operators.suboperators.fuzzy_implication_operator import \
    DiscreteFuzzyImplicationOperator
from discrete_fuzzy_morphology.base.structuring_element import StructuringElement


def fuzzy_image_erosion(image: numpy.ndarray,
                        structuring_element: StructuringElement,
                        iterations: int,
                        implication: DiscreteFuzzyImplicationOperator) -> numpy.ndarray:
    """
    Applies the fuzzy erosion to a grayscale image.

    Args:
        image: A numpy array, representing the image to be eroded.
        structuring_element: A StructuringElement object, representing the properties and the shape of the
                             structuring element to be used.
        iterations: An integer, representing the number of times that the erosion has to be applied to the image.
        implication: A DiscreteFuzzyImplicationOperator object, representing the implication to be used.

    References:
        <NAME>., & <NAME>. (2014).
        A fuzzy mathematical morphology based on discrete t-norms: fundamentals and applications to image processing.
        Soft Computing, 18 (11), 2297–2311. https://doi.org/10.1007/s00500-013-1204-6

    Returns:
        An image with the same dimension as the input image, representing the eroded image.
    """
    if not implication.is_implication():
        warnings.warn("The selected operator is not a fuzzy implication function. Results may not be correct.")

    img_rows, img_columns = image.shape
    se_rows, se_columns = structuring_element.dimension

    erosion_result = image.copy()

    iteration = image.copy()
    for _ in range(0, iterations):

        for i in range(0, img_rows):
            for j in range(0, img_columns):
                min_value = 255

                for ii in range(0, se_rows):
                    for jj in range(0, se_columns):
                        try:
                            x_value = structuring_element.evaluate(x=jj, y=ii)
                            y_value = iteration[i+ii-structuring_element.center[0], j+jj-structuring_element.center[1]]

                            implication_value = implication.evaluate_operator(x=x_value, y=y_value)

                            if implication_value < min_value:
                                min_value = implication_value
                        except:
                            continue
                erosion_result[i, j] = min_value
        iteration = erosion_result.copy()

    return erosion_result


Applies the fuzzy erosion to a grayscale image.      Args:         image: A numpy array, representing the image to be eroded.         structuring_element: A StructuringElement object, representing the properties and the shape of the                              structuring element to be used.         iterations: An integer, representing the number of times that the erosion has to be applied to the image.         implication: A DiscreteFuzzyImplicationOperator object, representing the implication to be used.      References:         <NAME>., & <NAME>. (2014).         A fuzzy mathematical morphology based on discrete t-norms: fundamentals and applications to image processing.         Soft Computing, 18 (11), 2297–2311. https://doi.org/10.1007/s00500-013-1204-6      Returns:         An image with the same dimension as the input image, representing the eroded image.