class TestIdentityCache(unittest.TestCase):
    def setUp(self):
        self.cache = IdentityCache()
        self.joe_ident = Identity('joe', ['rotate', 3], ['local', None, 'joe'])
        self.mitzi_ident = mockup('mitzi')
        self.atlas_ident = mockup('atlas')
        self.victor_ident = mockup('victor')

    def test_setitem_wrong_type(self):
        self.assertRaisesRegexp(TypeError,
                                "Expected ejtp.identity.core.Identity",
                                self.cache.__setitem__, self.joe_ident, [])

    def test_setitem_wrong_location(self):
        self.assertRaisesRegexp(ValueError,
                                "Trying to cache ident in the wrong location",
                                self.cache.__setitem__, ['x', 'y', 'z'],
                                self.joe_ident)

    def test_update_idents(self):
        idents = [self.joe_ident, self.victor_ident]
        self.cache.update_idents(idents)
        self.assertEquals(sorted(self.cache.all(), key=lambda x: x.key),
                          sorted(idents, key=lambda x: x.key))
        for i in idents:
            self.assertEquals(self.cache[i.location], i)

    def test_filter_by_name(self):
        # Create alternate-universe Joe
        alt_joe = self.joe_ident.clone()
        alt_joe.location = ['local', None, 'alt_joe']

        idents = [self.mitzi_ident, self.joe_ident, alt_joe]
        self.cache.update_idents(idents)

        self.assertEqual(self.cache.filter_by_name(self.mitzi_ident.name),
                         [self.mitzi_ident])

        joe_filtered = self.cache.filter_by_name(self.joe_ident.name)
        self.assertEqual(
            sorted(joe_filtered, key=lambda x: x.key),
            sorted([self.joe_ident, alt_joe], key=lambda x: x.key))

    def test_serialize(self):
        self.cache.update_ident(self.mitzi_ident)
        serialized_ident = self.cache.serialize()
        self.assertIn('["local",null,"mitzi"]', serialized_ident)

    def test_encrypt_capable(self):
        self.cache.update_ident(self.mitzi_ident)
        self.cache.update_ident(self.atlas_ident.public())
        self.cache.update_ident(self.joe_ident)

        capable = [ident.name for ident in self.cache.encrypt_capable()]
        self.assertIn('joe', capable)
        self.assertIn('*****@*****.**', capable)
        self.assertNotIn('*****@*****.**', capable)

    def _assert_caches(self, cache1, cache2):
        for item in zip(sorted(cache1.cache.keys()),
                        sorted(cache2.cache.keys())):
            self.assertEqual(*item)

    def test_sync(self):
        mitzi_cache = IdentityCache()
        atlas_cache = IdentityCache()
        mitzi_cache.update_ident(self.mitzi_ident)
        atlas_cache.update_ident(self.atlas_ident)
        mitzi_cache.sync(atlas_cache)
        self._assert_caches(mitzi_cache, atlas_cache)

    def test_deserialize(self):
        self.cache.update_ident(self.mitzi_ident)
        self.cache.update_ident(self.atlas_ident)

        serialization = self.cache.serialize()
        new_cache = IdentityCache()
        new_cache.deserialize(serialization)
        self._assert_caches(self.cache, new_cache)

    def test_load_from_without_args(self):
        self.assertRaisesRegexp(
            ValueError, 'Must provide either file_path or file_object',
            self.cache.load_from)

    def test_load(self):
        self.cache.load_from(testing_path('examplecache.json'))
        atlas_location = self.cache.find_by_name(
            "*****@*****.**").location
        self.assertListEqual(self.atlas_ident.location, atlas_location)

    def test_save_to_without_args(self):
        self.assertRaisesRegexp(
            ValueError, 'Must provide either file_path or file_object',
            self.cache.save_to)

    def test_save_to(self):
        filename = 'temp.json'
        self.cache.update_ident(self.mitzi_ident)
        self.cache.save_to(filename, indent=4)
        os.remove(filename)