import groovy.json.JsonBuilder
import ch.nevis.esauth.auth.engine.AuthResponse


def getHeader(String name) {
    def inctx = request.getLoginContext()
    // case-insensitive lookup of HTTP headers
    def map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER)
    map.putAll(inctx)
    return map['connection.HttpHeader.' + name]
}

def clearFidoUAFSession() {
    LOG.debug("start new FIDO UAF session (skipping ${session['ch.nevis.auth.fido.uaf.fidouafsessionid']}")
    def s = request.getAuthSession(true)
    s.removeAttribute('ch.nevis.auth.fido.uaf.fidouafsessionid')
    inargs.remove('fallback')
}


def clearIdmSessionAttributes() {
  def s = request.getAuthSession(true)
  def sessionKeySet = new HashSet(session.keySet()) 
  sessionKeySet.each { key -> 
    if ( key ==~ /ch.nevis.idm.*/ || key ==~ /ch.adnovum.nevisidm.*/ ) {
      s.removeAttribute(key)
    }
  }
}


// check, whether we are still processing the correct AuthnRequest
if (inargs.containsKey('authRequestId') && (inargs['authRequestId'] != session['ch.nevis.auth.saml.request.id'])) {
    // wrong request, "force" a timeout
    LOG.debug('authentication timeout enforced, due to concurrent requests -> return a 408')

    response.setIsDirectResponse(true)
    response.setContentType('text/html; charset=UTF-8')
    response.setContent('Timeout')
    response.setHttpStatusCode(205)
    response.setHeader('IDP-AUTH', 'Timeout')

    // CONTINUE to keep the other request beeing processed
    response.setStatus(AuthResponse.AUTH_CONTINUE)
    return
}

// dispatch AJAX calls and form POST when operation is done
if (inargs['fidoUafDone'] == 'true' ||
    inargs.containsKey('o.fidoUafSessionId.v') ||
    getHeader('Content-Type') == 'application/json') {

    if (inargs.containsKey('o.fidoUafSessionId.v') && (inargs['o.fidoUafSessionId.v'] != session['ch.nevis.auth.fido.uaf.fidouafsessionid'])) {
        // received polling for wrong fido session; make sure, that stops
        LOG.debug("received polling for wrong fido session ${inargs['o.fidoUafSessionId.v']} (correct: ${session['ch.nevis.auth.fido.uaf.fidouafsessionid']})")
        def json = new JsonBuilder()
        json {
            "status" "unknown"
            "timestamp" org.joda.time.DateTime.now().toString()
        }
        String body = json.toString()

        response.setContent(body)
        response.setContentType('application/json')
        response.setHttpStatusCode(200)
        response.setIsDirectResponse(true)
        response.setStatus(AuthResponse.AUTH_CONTINUE)
        return
    }

  if (inargs['fidoUafDone'] == 'true') {
    // get clean state, before validating user in IDM
    LOG.debug("clear IDM session attributes")
    clearIdmSessionAttributes()
  }

    // continue with OutOfBandFidoUafAuthState
    response.setResult('ok')
}

// dispatch form post with fallback input field : transition to FIDO Token authentication
if (inargs['fallback'] == 'fallback') {
    response.setResult('fido2')
}
    // dispatch to recovery
    if (inargs['fallback'] == 'recovery') {
    response.addOutArg('nevis.transfer.destination', parameters.get('recoveryurl'))
    response.setStatus(ch.nevis.esauth.auth.engine.AuthResponse.AUTH_CONTINUE) 
    response.setIsRedirectTransfer(true)
    // Remove existing cookies before redirecting to RECOVERY
    def agovRecoveryCookie = "agovRecovery=deleted; Path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Strict; Secure; HttpOnly"
    response.setHeader('Set-Cookie', agovRecoveryCookie)
    return
}

// dispatch form post with onReload input field : refresh QR-code FIDO UAF
if (inargs.containsKey('onReload')) {
    clearFidoUAFSession()
    response.setResult('default')
}

// dispatch form post with fallback input field : go to registration with right loa
if (inargs['fallback'] == 'register') {
   response.setResult('registration')
}