import unittest

import vapoursynth as vs


class PropDictTest(unittest.TestCase):
    def setUp(self):
        self.core = vs.core
        self.core.num_threads = 1
        self.frame = self.core.std.BlankClip().get_frame(0)
        self.props = self.frame.props

        self.frame_copy = self.frame.copy()
        self.props_rw = self.frame_copy.props

    def test_video_props(self):
        self.core.std.BlankClip().get_frame(0).props

    def test_audio_props(self):
        self.core.std.BlankAudio().get_frame(0).props

    def test_item_access(self):
        self.assertEqual(self.props["_DurationDen"], 24)
        with self.assertRaises(KeyError):
            self.props["_NonExistent"]

        with self.assertRaises(vs.Error):
            self.props["_DurationDen"] = 1

        with self.assertRaises(vs.Error):
            del self.props["_DurationDen"]

        self.assertEqual(self.props["_DurationDen"], 24)

        self.assertEqual(self.props_rw["_DurationDen"], 24)
        self.props_rw["_DurationDen"] = 1
        self.assertEqual(self.props_rw["_DurationDen"], 1)
        del self.props_rw["_DurationDen"]
        self.assertFalse("_DurationDen" in self.props_rw)

    def test_length(self):
        self.assertCountEqual(self.props, self.props_rw)
        self.assertEqual(len(self.props_rw), 2)
        del self.props_rw["_DurationDen"]
        self.assertEqual(len(self.props_rw), 1)
        self.props_rw["_DurationDen"] = 1
        self.assertEqual(len(self.props_rw), 2)
        self.props_rw["TestEntry"] = "123"
        self.assertEqual(len(self.props_rw), 3)

    def test_iterators(self):
        self.assertEqual(list(self.props.keys()), list(self.props))
        self.assertEqual(self.props.keys(), set(["_DurationDen", "_DurationNum"]))
        self.assertEqual(list(self.props.values()), [24, 1])
        self.assertEqual(self.props.items(), {("_DurationDen", 24), ("_DurationNum", 1)})
        self.assertEqual(dict(self.props), dict(self.props_rw))
        self.assertEqual(dict(self.props), {"_DurationDen": 24, "_DurationNum": 1})

    def test_get_pop(self):
        self.assertEqual(self.props.get("_DurationDen"), 24)
        self.assertEqual(self.props.get("_NonExistent"), None)
        self.assertEqual(self.props.get("_NonExistent", "Testificate"), "Testificate")

        with self.assertRaises(KeyError):
            self.props.pop("_NonExistent")

        x = []
        self.assertTrue(self.props.pop("_NonExistent", x) is x)
        self.assertEqual(self.props.pop("_NonExistent", None), None)
        self.assertEqual(self.props.pop("_NonExistent", "Testificate"), "Testificate")

        self.assertEqual(self.props_rw.pop("_DurationDen"), 24)
        with self.assertRaises(KeyError):
            self.props_rw.pop("_DurationDen")
        self.assertEqual(self.props_rw.pop("_DurationDen", "Test"), "Test")
        self.assertEqual(self.props_rw.popitem(), ("_DurationNum", 1))

    def test_setdefault(self):
        self.assertEqual(self.props_rw.setdefault("_DurationDen"), 24)
        self.assertFalse("_NonExistent1" in self.props_rw)
        self.assertEqual(self.props_rw.setdefault("_NonExistent1"), 0)
        self.assertEqual(self.props_rw["_NonExistent1"], 0)

        self.assertEqual(self.props_rw.setdefault("_NonExistent2", b"Testificate"), b"Testificate")
        self.assertEqual(self.props_rw["_NonExistent2"], b"Testificate")

    def test_attr_access(self):
        self.assertEqual(self.props._DurationDen, 24)
        with self.assertRaises(AttributeError):
            self.props._NonExistent

        with self.assertRaises(vs.Error):
            self.props._DurationDen = 1

        with self.assertRaises(vs.Error):
            del self.props._DurationDen

        self.assertEqual(self.props._DurationDen, 24)

        self.assertEqual(self.props_rw._DurationDen, 24)
        self.props_rw._DurationDen = 1
        self.assertEqual(self.props_rw._DurationDen, 1)
        del self.props_rw._DurationDen
        self.assertFalse(hasattr(self.props_rw, "_DurationDen"))

    def test_data_props(self):
        self.props_rw.DataPropStr = "hello"
        self.props_rw.DataPropBytes = b"hello"
        self.assertEqual(type(self.props_rw.DataPropStr), str)
        self.assertEqual(type(self.props_rw.DataPropBytes), bytes)


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