import numpy as np


def smooth_bruckner(y, smooth_points, iterations):
    """
    Calculates the Bruckner smooth background
    :param y: y values of the pattern
    :param smooth_points: the width of the smoothing window
    :param iterations: number of iterations the algorithms uses
    :return: smoothed background
    """
    y_original = y
    N_data = y.size
    N = smooth_points
    N_float = float(N)
    y = np.empty(N_data + N + N)

    y[0:N].fill(y_original[0])
    y[N:N + N_data] = y_original[0:N_data]
    y[N + N_data:N_data + N + N].fill(y_original[-1])

    y_avg = np.average(y)
    y_min = np.min(y)

    y_c = y_avg + 2. * (y_avg - y_min)
    y[y > y_c] = y_c

    window_size = N_float * 2 + 1

    for j in range(0, iterations):
        window_avg = np.average(y[0: 2 * N + 1])
        for i in range(N, N_data - 1 - N - 1):
            if y[i] > window_avg:
                y_new = window_avg
                # updating central value in average (first bracket)
                # and shifting average by one index (second bracket)
                window_avg += ((window_avg - y[i]) + (y[i + N + 1] - y[i - N])) / window_size
                y[i] = y_new
            else:
                # shifting average by one index
                window_avg += (y[i + N + 1] - y[i - N]) / window_size
    return y[N:N + N_data]
