import unittest

import numpy as np

import ex2.resizer_cython_impl as cyimpl
import ex2.resizer_numba_impl as nbimpl
import ex2.resizer_python_impl as pyimpl

F = np.nan


def test_resize(source, dw, dh, dest_desired):
    actual = pyimpl.resize(np.array(source), dw, dh)
    np.testing.assert_almost_equal(actual, np.array(dest_desired), err_msg='Python resizer impl.')
    actual = cyimpl.resize(np.array(source), dw, dh)
    np.testing.assert_almost_equal(actual, np.array(dest_desired), err_msg='Cython resizer impl.')
    actual = nbimpl.resize(np.array(source), dw, dh)
    np.testing.assert_almost_equal(actual, np.array(dest_desired), err_msg='Numba resizer impl.')


class ResizerTest(unittest.TestCase):
    """
    Note: Always align this test with java/src/test/java/com/bc/perfcomp/ex2/ResizerTest.java
    """

    def test_no_op(self):
        test_resize([[1., 2.], [3., 4.]],
                    2, 2,
                    [[1., 2.], [3., 4.]])

    def test_interpolation(self):
        test_resize([[1., 2., 3.]],
                    5, 1,
                    [[1, 1.5, 2, 2.5, 3]]),

        test_resize([[1., 2., 3.]],
                    9, 1,
                    [[1, 1.25, 1.5, 1.75, 2, 2.25, 2.5, 2.75, 3]])

        test_resize([[1., 2., 3., 4.]],
                    6, 1,
                    [[1, 1.6, 2.2, 2.8, 3.4, 4]]),

        test_resize([[1., 2.],
                     [3., 4.]],
                    4, 4,
                    [[3. / 3, 4. / 3, 5. / 3, 6. / 3],
                     [5. / 3, 6. / 3, 7. / 3, 8. / 3],
                     [7. / 3, 8. / 3, 9. / 3, 10. / 3],
                     [9. / 3, 10. / 3, 11. / 3, 12. / 3]]),

        test_resize([[1., 2.],
                     [3., 4.]],
                    4, 4,
                    [[3. / 3, 4. / 3, 5. / 3, 6. / 3],
                     [5. / 3, 6. / 3, 7. / 3, 8. / 3],
                     [7. / 3, 8. / 3, 9. / 3, 10. / 3],
                     [9. / 3, 10. / 3, 11. / 3, 12. / 3]])

    def test_aggregation(self):
        test_resize([[0.6, 0.2, 3.4],
                     [1.4, 1.6, 1.0],
                     [4.0, 2.8, 3.0]],
                    2, 2,
                    [[(0.6 + 0.5 * 0.2 + 0.5 * 1.4 + 0.25 * 1.6) / (1.0 + 0.5 + 0.5 + 0.25),
                      (3.4 + 0.5 * 0.2 + 0.5 * 1.0 + 0.25 * 1.6) / (1.0 + 0.5 + 0.5 + 0.25)],
                     [(4.0 + 0.5 * 1.4 + 0.5 * 2.8 + 0.25 * 1.6) / (1.0 + 0.5 + 0.5 + 0.25),
                      (3.0 + 0.5 * 1.0 + 0.5 * 2.8 + 0.25 * 1.6) / (1.0 + 0.5 + 0.5 + 0.25)]])

        test_resize([[0.9, 0.5, 3.0, 4.0],
                     [1.1, 1.5, 1.0, 2.0],
                     [4.0, 2.1, 3.0, 5.0],
                     [3.0, 4.9, 3.0, 1.0]],
                    2, 2,
                    [[1.0, 2.5],
                     [3.5, 3.0]])
