'''LSST-specific CILogon OAuthenticator class, delegating its LSST-specific
authentication logic to its auth_mgr.
'''
import oauthenticator
from tornado import gen
from .lsstauth import LSSTAuthenticator
from ..lsstmgr import check_membership
from ..utils import make_logger


class LSSTCILogonOAuthenticator(LSSTAuthenticator,
                                oauthenticator.CILogonOAuthenticator):
    login_handler = oauthenticator.CILogonLoginHandler
    _default_domain = None

    def __init__(self, *args, **kwargs):
        self.log = make_logger()
        self.log.debug("Creating LSSTCILogonOAuthenticator")
        super().__init__(*args, **kwargs)

    @gen.coroutine
    def authenticate(self, handler, data=None):
        '''Authenticate and set UID/groups on auth_mgr.
        '''
        self.log.info("Authenticating user against CILogon.")
        cfg = self.lsst_mgr.config
        userdict = yield super().authenticate(handler, data)
        if not userdict:
            return None
        ast = yield self.user.get_auth_state()
        uid, groupmap = self.resolve_cilogon(ast['cilogon_user'])
        groups = groupmap.keys()
        membership = check_membership(groups, cfg.allowed_groups,
                                      cfg.forbidden_groups, log=self.log)
        if not membership:
            self.log.warning("Group membership check failed.")
            return None
        ast['group_map'] = groupmap
        user_rec = ast["cilogon_user"]
        username = user_rec["uid"]
        if "eppn" in user_rec:
            username, domain = user_rec["eppn"].split("@")
        else:
            domain = ""
        if domain and self._default_domain and domain != self._default_domain:
            username = username + "." + domain
            userdict["name"] = username
        return userdict
