import ch.nevis.esauth.auth.states.saml.util.Communicator

boolean isLevel(String role) {
    if (role != null && role.isNumber()) {
        def number = Integer.parseInt(role)
        if (number > 0 && number <= 9) {
            return true
        }
    }
    return false
}

def populateRequiredRoles() {
    def requiredRoles = request.getRequiredRoles()
    // set required roles on Session Upgrade Path
    if (requiredRoles == null || requiredRoles.length == 0) {
        if (inargs.containsKey('level')) {
            def level = inargs.get('level')
            LOG.debug("requested authentication level $level on session upgrade path")
            String[] roles = [ level ]
            request.setRequiredRoles(roles)
        }
        else {
            LOG.debug('no authentication level requested')
            // set a dummy role which never exists
            // to force the SP to send an AuthnRequest to the IDP
            String[] roles = [ 'dummy' ]
            request.setRequiredRoles(roles)
        }
    }
    // stepup triggered by Authorization Policy with Authentication Level
    else if (requiredRoles.length > 1) {
        // we strip this down to send only the desired level to the IDP
        def level = requiredRoles.min()
        LOG.debug("required minimum authentication level: $level")
        String[] roles = [ level ]
        request.setRequiredRoles(roles)
    }
}

// redirect back to application if on Session Upgrade Path
def handleSessionUpgradePathRelayState() {
    if (inargs.containsKey('relayState')) {
        def encodedRelayState = inargs.get('relayState')
        def communicator = new Communicator()
        def url = communicator.decodeRelayState(encodedRelayState)
        if (url != null) {
            LOG.debug("user will be redirected to $url")
            outargs.put('nevis.transfer.destination', url)
        }
    }
}

if (inargs.containsKey('SAMLResponse')) {
    // consume SAML Response from IDP
    LOG.debug('received SAML Response')
    return // continue with ResultCond default
}

populateRequiredRoles()

// if any of the required authentication levels is already achieved
// then we can terminate the stepup early
// this is a work-around for SecurityRoleFilter
// which does not notice when the stepup process ends with AUTH_DONE on a different location
for (String role : request.getRequiredRoles()) {
    if (isLevel(role)) {
        LOG.debug("found level: $role")
        def range = Integer.parseInt(role)..9
        for (Integer level : range) { // higher levels are fine as well
            LOG.debug("checking if level $level has been reached...")
            if (response.actualRoles.contains("$level")) {
                LOG.debug("required level $level has already been reached - skipping session upgrade")
                handleSessionUpgradePathRelayState()
                response.setResult('done')
                return
            }
        }
    }
}

if (session.containsKey('force-saml-authn')) {
    LOG.debug('clearing force-saml-authn flag')
    // clear marker
    session.remove('force-saml-authn')
    handleSessionUpgradePathRelayState()
}
else {
    LOG.debug('setting force-saml-authn')
    session.put('force-saml-authn', 'true')
}
