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, 'monai.utils.optional_import', 'optional_import', (['"""cucim"""'], {}), False, 'from monai.utils import optional_import\n'), (15, 'monai.utils.optional_import', 'optional_import', (['"""openslide"""'], {}), False, 'from monai.utils import optional_import\n'), (18, 'os.path.dirname', 'os.path.dirname', (['__file__'], {}), False, 'import os\n'), (18, 'os.path.basename', 'os.path.basename', (['FILE_URL'], {}), False, 'import os\n'), (20, 'os.path.dirname', 'os.path.dirname', (['__file__'], {}), False, 'import os\n'), (21, 'os.path.dirname', 'os.path.dirname', (['__file__'], {}), False, 'import os\n'), (22, 'os.path.dirname', 'os.path.dirname', (['__file__'], {}), False, 'import os\n'), (30, 'numpy.zeros', 'np.zeros', (['(WIDTH // 2, HEIGHT // 2)'], {}), True, 'import numpy as np\n'), (32, 'numpy.save', 'np.save', (['MASK1', 'mask'], {}), True, 'import numpy as np\n'), (34, 'numpy.save', 'np.save', (['MASK2', 'mask'], {}), True, 'import numpy as np\n'), (36, 'numpy.save', 'np.save', (['MASK4', 'mask'], {}), True, 'import numpy as np\n'), (202, 'parameterized.parameterized.expand', 'parameterized.expand', (['[TEST_CASE_0, TEST_CASE_1, TEST_CASE_2, TEST_CASE_3, TEST_CASE_4]'], {}), False, 'from parameterized import parameterized\n'), (211, 'unittest.skipUnless', 'skipUnless', (['has_cim', '"""Requires CuCIM"""'], {}), False, 'from unittest import skipUnless\n'), (217, 'parameterized.parameterized.expand', 'parameterized.expand', (['[TEST_CASE_OPENSLIDE_0, TEST_CASE_OPENSLIDE_1]'], {}), False, 'from parameterized import parameterized\n'), (223, 'unittest.skipUnless', 'skipUnless', (['has_osl', '"""Requires OpenSlide"""'], {}), False, 'from unittest import skipUnless\n'), (238, 'unittest.main', 'unittest.main', ([], {}), False, 'import unittest\n'), (200, 'monai.apps.utils.download_url', 'download_url', (['FILE_URL', 'FILE_PATH', '"""5a3cfd4fd725c50578ddb80b517b759f"""'], {}), False, 'from monai.apps.utils import download_url\n'), (214, 'monai.apps.pathology.datasets.MaskedInferenceWSIDataset', 'MaskedInferenceWSIDataset', ([], {}), False, 'from monai.apps.pathology.datasets import MaskedInferenceWSIDataset\n'), (226, 'monai.apps.pathology.datasets.MaskedInferenceWSIDataset', 'MaskedInferenceWSIDataset', ([], {}), False, 'from monai.apps.pathology.datasets import MaskedInferenceWSIDataset\n'), (49, 'numpy.array', 'np.array', (['[[[243]], [[243]], [[243]]]'], {'dtype': 'np.uint8'}), True, 'import numpy as np\n'), (64, 'numpy.array', 'np.array', (['[[[243]], [[243]], [[243]]]'], {'dtype': 'np.uint8'}), True, 'import numpy as np\n'), (69, 'numpy.array', 'np.array', (['[[[243]], [[243]], [[243]]]'], {'dtype': 'np.uint8'}), True, 'import numpy as np\n'), (84, 'numpy.array', 'np.array', (['[[[243]], [[243]], [[243]]]'], {'dtype': 'np.uint8'}), True, 'import numpy as np\n'), (89, 'numpy.array', 'np.array', (['[[[243]], [[243]], [[243]]]'], {'dtype': 'np.uint8'}), True, 'import numpy as np\n'), (94, 'numpy.array', 'np.array', (['[[[243]], [[243]], [[243]]]'], {'dtype': 'np.uint8'}), True, 'import numpy as np\n'), (99, 'numpy.array', 'np.array', (['[[[243]], [[243]], [[243]]]'], {'dtype': 'np.uint8'}), True, 'import numpy as np\n'), (116, 'numpy.array', 'np.array', (['[[[243, 243], [243, 243]], [[243, 243], [243, 243]], [[243, 243], [243, 243]]]'], {'dtype': 'np.uint8'}), True, 'import numpy as np\n'), (141, 'numpy.array', 'np.array', (['[[[243]], [[243]], [[243]]]'], {'dtype': 'np.uint8'}), True, 'import numpy as np\n'), (146, 'numpy.array', 'np.array', (['[[[243]], [[243]], [[243]]]'], {'dtype': 'np.uint8'}), True, 'import numpy as np\n'), (151, 'numpy.array', 'np.array', (['[[[243]], [[243]], [[243]]]'], {'dtype': 'np.uint8'}), True, 'import numpy as np\n'), (169, 'numpy.array', 'np.array', (['[[[243]], [[243]], [[243]]]'], {'dtype': 'np.uint8'}), True, 'import numpy as np\n'), (184, 'numpy.array', 'np.array', (['[[[243]], [[243]], [[243]]]'], {'dtype': 'np.uint8'}), True, 'import numpy as np\n'), (189, 'numpy.array', 'np.array', (['[[[243]], [[243]], [[243]]]'], {'dtype': 'np.uint8'}), True, 'import numpy as np\n'), (232, 'numpy.testing.assert_array_equal', 'assert_array_equal', (["dataset[i][0]['image']", "expected[i]['image']"], {}), False, 'from numpy.testing import assert_array_equal\n')]