# Copyright 2017 Canonical Ltd.
# Licensed under the LGPLv3, see LICENCE file for details.
try:
    from collections.abc import Mapping
except ImportError:
    from collections import Mapping


class AuthContext(Mapping):
    ''' Holds a set of keys and values relevant to authorization.

    It is passed as an argument to authorization checkers, so that the checkers
    can access information about the context of the authorization request.
    It is immutable - values can only be added by copying the whole thing.
    '''
    def __init__(self, somedict=None):
        if somedict is None:
            somedict = {}
        self._dict = dict(somedict)
        self._hash = None

    def with_value(self, key, val):
        ''' Return a copy of the AuthContext object with the given key and
        value added.
        '''
        new_dict = dict(self._dict)
        new_dict[key] = val
        return AuthContext(new_dict)

    def __getitem__(self, key):
        return self._dict[key]

    def __len__(self):
        return len(self._dict)

    def __iter__(self):
        return iter(self._dict)

    def __hash__(self):
        if self._hash is None:
            self._hash = hash(frozenset(self._dict.items()))
        return self._hash

    def __eq__(self, other):
        return self._dict == other._dict


class ContextKey(object):
    '''Provides a unique key suitable for use as a key into AuthContext.'''

    def __init__(self, name):
        '''Creates a context key using the given name. The name is
     only for informational purposes.
     '''
        self._name = name

    def __str__(self):
        return '%s#%#x' % (self._name, id(self))

    def __repr__(self):
        return 'context_key(%r, %#x)' % (self._name, id(self))
