import os
import unittest
from unittest import skipUnless

import numpy as np
from numpy.testing import assert_array_equal
from parameterized import parameterized

from monai.apps.pathology.datasets import MaskedInferenceWSIDataset
from monai.apps.utils import download_url
from monai.utils import optional_import
from tests.utils import skip_if_quick

_, has_cim = optional_import("cucim")
_, has_osl = optional_import("openslide")

FILE_URL = "http://openslide.cs.cmu.edu/download/openslide-testdata/Generic-TIFF/CMU-1.tiff"
FILE_PATH = os.path.join(os.path.dirname(__file__), "testing_data", os.path.basename(FILE_URL))

MASK1 = os.path.join(os.path.dirname(__file__), "testing_data", "tissue_mask1.npy")
MASK2 = os.path.join(os.path.dirname(__file__), "testing_data", "tissue_mask2.npy")
MASK4 = os.path.join(os.path.dirname(__file__), "testing_data", "tissue_mask4.npy")

HEIGHT = 32914
WIDTH = 46000


def prepare_data():

    mask = np.zeros((WIDTH // 2, HEIGHT // 2))
    mask[100, 100] = 1
    np.save(MASK1, mask)
    mask[100, 100:102] = 1
    np.save(MASK2, mask)
    mask[100:102, 100:102] = 1
    np.save(MASK4, mask)


TEST_CASE_0 = [
    {
        "data": [
            {"image": FILE_PATH, "mask": MASK1},
        ],
        "patch_size": 1,
        "image_reader_name": "cuCIM",
    },
    [
        {
            "image": np.array([[[243]], [[243]], [[243]]], dtype=np.uint8),
            "name": "CMU-1",
            "mask_location": [100, 100],
        },
    ],
]

TEST_CASE_1 = [
    {
        "data": [{"image": FILE_PATH, "mask": MASK2}],
        "patch_size": 1,
        "image_reader_name": "cuCIM",
    },
    [
        {
            "image": np.array([[[243]], [[243]], [[243]]], dtype=np.uint8),
            "name": "CMU-1",
            "mask_location": [100, 100],
        },
        {
            "image": np.array([[[243]], [[243]], [[243]]], dtype=np.uint8),
            "name": "CMU-1",
            "mask_location": [101, 100],
        },
    ],
]

TEST_CASE_2 = [
    {
        "data": [{"image": FILE_PATH, "mask": MASK4}],
        "patch_size": 1,
        "image_reader_name": "cuCIM",
    },
    [
        {
            "image": np.array([[[243]], [[243]], [[243]]], dtype=np.uint8),
            "name": "CMU-1",
            "mask_location": [100, 100],
        },
        {
            "image": np.array([[[243]], [[243]], [[243]]], dtype=np.uint8),
            "name": "CMU-1",
            "mask_location": [100, 101],
        },
        {
            "image": np.array([[[243]], [[243]], [[243]]], dtype=np.uint8),
            "name": "CMU-1",
            "mask_location": [101, 100],
        },
        {
            "image": np.array([[[243]], [[243]], [[243]]], dtype=np.uint8),
            "name": "CMU-1",
            "mask_location": [101, 101],
        },
    ],
]

TEST_CASE_3 = [
    {
        "data": [
            {"image": FILE_PATH, "mask": MASK1},
        ],
        "patch_size": 2,
        "image_reader_name": "cuCIM",
    },
    [
        {
            "image": np.array(
                [
                    [[243, 243], [243, 243]],
                    [[243, 243], [243, 243]],
                    [[243, 243], [243, 243]],
                ],
                dtype=np.uint8,
            ),
            "name": "CMU-1",
            "mask_location": [100, 100],
        },
    ],
]

TEST_CASE_4 = [
    {
        "data": [
            {"image": FILE_PATH, "mask": MASK1},
            {"image": FILE_PATH, "mask": MASK2},
        ],
        "patch_size": 1,
        "image_reader_name": "cuCIM",
    },
    [
        {
            "image": np.array([[[243]], [[243]], [[243]]], dtype=np.uint8),
            "name": "CMU-1",
            "mask_location": [100, 100],
        },
        {
            "image": np.array([[[243]], [[243]], [[243]]], dtype=np.uint8),
            "name": "CMU-1",
            "mask_location": [100, 100],
        },
        {
            "image": np.array([[[243]], [[243]], [[243]]], dtype=np.uint8),
            "name": "CMU-1",
            "mask_location": [101, 100],
        },
    ],
]


TEST_CASE_OPENSLIDE_0 = [
    {
        "data": [
            {"image": FILE_PATH, "mask": MASK1},
        ],
        "patch_size": 1,
        "image_reader_name": "OpenSlide",
    },
    [
        {
            "image": np.array([[[243]], [[243]], [[243]]], dtype=np.uint8),
            "name": "CMU-1",
            "mask_location": [100, 100],
        },
    ],
]

TEST_CASE_OPENSLIDE_1 = [
    {
        "data": [{"image": FILE_PATH, "mask": MASK2}],
        "patch_size": 1,
        "image_reader_name": "OpenSlide",
    },
    [
        {
            "image": np.array([[[243]], [[243]], [[243]]], dtype=np.uint8),
            "name": "CMU-1",
            "mask_location": [100, 100],
        },
        {
            "image": np.array([[[243]], [[243]], [[243]]], dtype=np.uint8),
            "name": "CMU-1",
            "mask_location": [101, 100],
        },
    ],
]


class TestMaskedInferenceWSIDataset(unittest.TestCase):
    def setUp(self):
        prepare_data()
        download_url(FILE_URL, FILE_PATH, "5a3cfd4fd725c50578ddb80b517b759f")

    @parameterized.expand(
        [
            TEST_CASE_0,
            TEST_CASE_1,
            TEST_CASE_2,
            TEST_CASE_3,
            TEST_CASE_4,
        ]
    )
    @skipUnless(has_cim, "Requires CuCIM")
    @skip_if_quick
    def test_read_patches_cucim(self, input_parameters, expected):
        dataset = MaskedInferenceWSIDataset(**input_parameters)
        self.compare_samples_expected(dataset, expected)

    @parameterized.expand(
        [
            TEST_CASE_OPENSLIDE_0,
            TEST_CASE_OPENSLIDE_1,
        ]
    )
    @skipUnless(has_osl, "Requires OpenSlide")
    @skip_if_quick
    def test_read_patches_openslide(self, input_parameters, expected):
        dataset = MaskedInferenceWSIDataset(**input_parameters)
        self.compare_samples_expected(dataset, expected)

    def compare_samples_expected(self, dataset, expected):
        for i in range(len(dataset)):
            self.assertTupleEqual(dataset[i][0]["image"].shape, expected[i]["image"].shape)
            self.assertIsNone(assert_array_equal(dataset[i][0]["image"], expected[i]["image"]))
            self.assertEqual(dataset[i][0]["name"], expected[i]["name"])
            self.assertListEqual(dataset[i][0]["mask_location"], expected[i]["mask_location"])


if __name__ == "__main__":
    unittest.main()

[((14, 13, 14, 37), 'monai.utils.optional_import', 'optional_import', ({(14, 29, 14, 36): '"""cucim"""'}, {}), "('cucim')", False, 'from monai.utils import optional_import\n'), ((15, 13, 15, 41), 'monai.utils.optional_import', 'optional_import', ({(15, 29, 15, 40): '"""openslide"""'}, {}), "('openslide')", False, 'from monai.utils import optional_import\n'), ((18, 25, 18, 50), 'os.path.dirname', 'os.path.dirname', ({(18, 41, 18, 49): '__file__'}, {}), '(__file__)', False, 'import os\n'), ((18, 68, 18, 94), 'os.path.basename', 'os.path.basename', ({(18, 85, 18, 93): 'FILE_URL'}, {}), '(FILE_URL)', False, 'import os\n'), ((20, 21, 20, 46), 'os.path.dirname', 'os.path.dirname', ({(20, 37, 20, 45): '__file__'}, {}), '(__file__)', False, 'import os\n'), ((21, 21, 21, 46), 'os.path.dirname', 'os.path.dirname', ({(21, 37, 21, 45): '__file__'}, {}), '(__file__)', False, 'import os\n'), ((22, 21, 22, 46), 'os.path.dirname', 'os.path.dirname', ({(22, 37, 22, 45): '__file__'}, {}), '(__file__)', False, 'import os\n'), ((30, 11, 30, 46), 'numpy.zeros', 'np.zeros', ({(30, 20, 30, 45): '(WIDTH // 2, HEIGHT // 2)'}, {}), '((WIDTH // 2, HEIGHT // 2))', True, 'import numpy as np\n'), ((32, 4, 32, 24), 'numpy.save', 'np.save', ({(32, 12, 32, 17): 'MASK1', (32, 19, 32, 23): 'mask'}, {}), '(MASK1, mask)', True, 'import numpy as np\n'), ((34, 4, 34, 24), 'numpy.save', 'np.save', ({(34, 12, 34, 17): 'MASK2', (34, 19, 34, 23): 'mask'}, {}), '(MASK2, mask)', True, 'import numpy as np\n'), ((36, 4, 36, 24), 'numpy.save', 'np.save', ({(36, 12, 36, 17): 'MASK4', (36, 19, 36, 23): 'mask'}, {}), '(MASK4, mask)', True, 'import numpy as np\n'), ((202, 5, 210, 5), 'parameterized.parameterized.expand', 'parameterized.expand', ({(203, 8, 209, 9): '[TEST_CASE_0, TEST_CASE_1, TEST_CASE_2, TEST_CASE_3, TEST_CASE_4]'}, {}), '([TEST_CASE_0, TEST_CASE_1, TEST_CASE_2, TEST_CASE_3,\n    TEST_CASE_4])', False, 'from parameterized import parameterized\n'), ((211, 5, 211, 42), 'unittest.skipUnless', 'skipUnless', ({(211, 16, 211, 23): 'has_cim', (211, 25, 211, 41): '"""Requires CuCIM"""'}, {}), "(has_cim, 'Requires CuCIM')", False, 'from unittest import skipUnless\n'), ((217, 5, 222, 5), 'parameterized.parameterized.expand', 'parameterized.expand', ({(218, 8, 221, 9): '[TEST_CASE_OPENSLIDE_0, TEST_CASE_OPENSLIDE_1]'}, {}), '([TEST_CASE_OPENSLIDE_0, TEST_CASE_OPENSLIDE_1])', False, 'from parameterized import parameterized\n'), ((223, 5, 223, 46), 'unittest.skipUnless', 'skipUnless', ({(223, 16, 223, 23): 'has_osl', (223, 25, 223, 45): '"""Requires OpenSlide"""'}, {}), "(has_osl, 'Requires OpenSlide')", False, 'from unittest import skipUnless\n'), ((238, 4, 238, 19), 'unittest.main', 'unittest.main', ({}, {}), '()', False, 'import unittest\n'), ((200, 8, 200, 77), 'monai.apps.utils.download_url', 'download_url', ({(200, 21, 200, 29): 'FILE_URL', (200, 31, 200, 40): 'FILE_PATH', (200, 42, 200, 76): '"""5a3cfd4fd725c50578ddb80b517b759f"""'}, {}), "(FILE_URL, FILE_PATH, '5a3cfd4fd725c50578ddb80b517b759f')", False, 'from monai.apps.utils import download_url\n'), ((214, 18, 214, 63), 'monai.apps.pathology.datasets.MaskedInferenceWSIDataset', 'MaskedInferenceWSIDataset', ({}, {}), '(**input_parameters)', False, 'from monai.apps.pathology.datasets import MaskedInferenceWSIDataset\n'), ((226, 18, 226, 63), 'monai.apps.pathology.datasets.MaskedInferenceWSIDataset', 'MaskedInferenceWSIDataset', ({}, {}), '(**input_parameters)', False, 'from monai.apps.pathology.datasets import MaskedInferenceWSIDataset\n'), ((49, 21, 49, 74), 'numpy.array', 'np.array', (), '', True, 'import numpy as np\n'), ((64, 21, 64, 74), 'numpy.array', 'np.array', (), '', True, 'import numpy as np\n'), ((69, 21, 69, 74), 'numpy.array', 'np.array', (), '', True, 'import numpy as np\n'), ((84, 21, 84, 74), 'numpy.array', 'np.array', (), '', True, 'import numpy as np\n'), ((89, 21, 89, 74), 'numpy.array', 'np.array', (), '', True, 'import numpy as np\n'), ((94, 21, 94, 74), 'numpy.array', 'np.array', (), '', True, 'import numpy as np\n'), ((99, 21, 99, 74), 'numpy.array', 'np.array', (), '', True, 'import numpy as np\n'), ((116, 21, 123, 13), 'numpy.array', 'np.array', (), '', True, 'import numpy as np\n'), ((141, 21, 141, 74), 'numpy.array', 'np.array', (), '', True, 'import numpy as np\n'), ((146, 21, 146, 74), 'numpy.array', 'np.array', (), '', True, 'import numpy as np\n'), ((151, 21, 151, 74), 'numpy.array', 'np.array', (), '', True, 'import numpy as np\n'), ((169, 21, 169, 74), 'numpy.array', 'np.array', (), '', True, 'import numpy as np\n'), ((184, 21, 184, 74), 'numpy.array', 'np.array', (), '', True, 'import numpy as np\n'), ((189, 21, 189, 74), 'numpy.array', 'np.array', (), '', True, 'import numpy as np\n'), ((232, 30, 232, 94), 'numpy.testing.assert_array_equal', 'assert_array_equal', ({(232, 49, 232, 71): "dataset[i][0]['image']", (232, 73, 232, 93): "expected[i]['image']"}, {}), "(dataset[i][0]['image'], expected[i]['image'])", False, 'from numpy.testing import assert_array_equal\n')]