# forward pass

from nn.conv.layers import im2row, filter2col, dotProdOutToImg
import numpy as np

### INPUTS
img = np.asarray([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]], dtype=np.float64).reshape(1, 1, 4, 4)
img = np.repeat(img, 2, axis=0)

filter = np.eye(3).reshape((1, 1, 3, 3))


### FORWARD PROPAGATION
im_as_rows = im2row(img, filter.shape)
filter_as_columns = filter2col(img.shape, filter)
out_image_as_rows = im_as_rows.dot(filter_as_columns)
desired_out_shape_before_axis_swap = (filter.shape[1], img.shape[0], img.shape[2], img.shape[3])
img_out = np.swapaxes(np.reshape(out_image_as_rows.T, desired_out_shape_before_axis_swap), 0, 1)

output_grad = np.random.randn(*img_out.shape)


### BACKWARD PROPAGATION
grad_out_image_as_rows = np.dot(im2row(output_grad, filter.shape), filter_as_columns)
grad_im_as_rows = grad_out_image_as_rows.dot(filter_as_columns.T)
grad_filter_as_columns = im_as_rows.T.dot(grad_out_image_as_rows)

print(grad_im_as_rows.shape)
grad_im = np.empty(img.shape)
dotProdOutToImg(grad_im_as_rows, filter.shape, img.shape, grad_im)
for b in [0, 1]:
    for channel_id, channel in enumerate(image_channels):
        counter = 1
        for row in range(image_size):
            for col in range(image_size):
                cell_content = Symbol("{2}{0}{1}".format(channel, counter, b))
                counter += 1
                image[b,channel_id,row,col] = cell_content



print("Original Image:")
print(image)

print("\nReshaped Image:")
reshaped_image = im2row(image, (len(image_channels), len(filter_channels), 3, 3))
print(reshaped_image)

print("\nBackshaped Image:")
backshaped_image = row2im(reshaped_image, labeled_filter.shape, image.shape)
print(backshaped_image)

print("\nDifference:")
print(backshaped_image - image)

# print(image + 1)
# print(np.dot(reshaped_image, properly_reshaped_filter).shape)



# print(row2im(np.dot(reshaped_image, properly_reshaped_filter), labeled_filter.shape, image.shape))