/*
 * Licensed to Apereo under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Apereo licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License.  You may obtain a
 * copy of the License at the following location:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package io.cos.cas.web.flow;

import io.cos.cas.adaptors.mongodb.OpenScienceFrameworkLogoutHandler;

import io.cos.cas.authentication.handler.support.OpenScienceFrameworkPrincipalFromRequestRemoteUserNonInteractiveCredentialsAction;
import org.jasig.cas.CentralAuthenticationService;
import org.jasig.cas.authentication.Authentication;
import org.jasig.cas.web.support.CookieRetrievingCookieGenerator;
import org.jasig.cas.web.support.WebUtils;
import org.jasig.cas.ticket.TicketGrantingTicket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.webflow.action.EventFactorySupport;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;


/**
 * The Open Science Framework Terminate Session Action.
 *
 * @author Longze Chen
 * @since 4.1.0
 */
public class OpenScienceFrameworkTerminateSessionAction {

    /** The logger instance. */
    protected final Logger logger = LoggerFactory.getLogger(getClass());


    /** Webflow event helper component. */
    private final EventFactorySupport eventFactorySupport = new EventFactorySupport();

    /** The CORE to which we delegate for all CAS functionality. */
    @NotNull
    private final CentralAuthenticationService centralAuthenticationService;

    /** CookieGenerator for TGT Cookie. */
    @NotNull
    private final CookieRetrievingCookieGenerator ticketGrantingTicketCookieGenerator;

    /** CookieGenerator for Warn Cookie. */
    @NotNull
    private final CookieRetrievingCookieGenerator warnCookieGenerator;
    /**
     * Creates a new instance with the given parameters.
     * @param cas Core business logic object.
     * @param tgtCookieGenerator TGT cookie generator.
     * @param warnCookieGenerator Warn cookie generator.
     */
    public OpenScienceFrameworkTerminateSessionAction(
            final CentralAuthenticationService cas,
            final CookieRetrievingCookieGenerator tgtCookieGenerator,
            final CookieRetrievingCookieGenerator warnCookieGenerator) {
        this.centralAuthenticationService = cas;
        this.ticketGrantingTicketCookieGenerator = tgtCookieGenerator;
        this.warnCookieGenerator = warnCookieGenerator;
    }

    /**
     * The Terminate Action.
     * @param context The Request Context
     * @return the Event success or finish
     */
    public Event terminate(final RequestContext context) {
        // in login's webflow : we can get the value from context as it has already been stored
        String tgtId = WebUtils.getTicketGrantingTicketId(context);

        String institutionId = "osf";
        Boolean remotePrincipal = Boolean.FALSE;

        // for logout, we need to get the cookie's value
        if (tgtId == null) {
            final HttpServletRequest request = WebUtils.getHttpServletRequest(context);
            tgtId = this.ticketGrantingTicketCookieGenerator.retrieveCookieValue(request);
        }
        // for institution logout, we need to get the TGT which contains the institutionId
        if (tgtId != null) {
            TicketGrantingTicket tgt = null;
            try {
                tgt  = centralAuthenticationService.getTicket(tgtId, TicketGrantingTicket.class);
            }
            catch (final Exception e) {
                //  ignore
            }
            if (tgt != null) {
                final Authentication auth = tgt.getAuthentication();
                if (auth != null) {
                    institutionId = (String) auth.getAttributes().get("institutionId");
                    remotePrincipal = (Boolean) auth.getAttributes().get("remotePrincipal");
                }
            }

            WebUtils.putLogoutRequests(context, this.centralAuthenticationService.destroyTicketGrantingTicket(tgtId));
        }
        final HttpServletResponse response = WebUtils.getHttpServletResponse(context);
        this.ticketGrantingTicketCookieGenerator.removeCookie(response);
        this.warnCookieGenerator.removeCookie(response);

        final HttpServletRequest request = WebUtils.getHttpServletRequest(context);
        final Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (final Cookie cookie : cookies) {
                if (cookie.getName().startsWith(
                        OpenScienceFrameworkPrincipalFromRequestRemoteUserNonInteractiveCredentialsAction.SHIBBOLETH_COOKIE_PREFIX)) {
                    logger.info("Remove shibboleth session cookie: {}", cookie.getName());
                    final Cookie shibbolethCookie = new Cookie(cookie.getName(), null);
                    shibbolethCookie.setMaxAge(0);
                    response.addCookie(shibbolethCookie);
                }
            }
        }

        // if users logged in through their institutions, redirect to institution logout endpoint
        if (remotePrincipal) {
            final String institutionLogoutUrl = OpenScienceFrameworkLogoutHandler.findInstitutionLogoutUrlById(institutionId);
            if (institutionLogoutUrl == null) {
                logger.warn("Institution {} does not have logout url, use default logout redirection instead", institutionId);
            }
            else {
                context.getFlowScope().put("logoutRedirectUrl", institutionLogoutUrl);
                return new Event(this, "finish");
            }
        }

        return this.eventFactorySupport.success(this);
    }
}

@@ -3583,13 +3583,12 @@
 d = 
-%22osf%22
+null
 ;%0A  
@@ -4414,32 +4414,113 @@
 auth != null) %7B%0A
+                    if (auth.getAttributes().containsKey(%22institutionId%22)) %7B%0A    
                 
@@ -4615,80 +4615,308 @@
     
-remotePrincipal = (Boolean) auth.getAttributes().get(%22remotePrincipal%22);
+%7D%0A                    if (auth.getAttributes().containsKey(%22remotePrincipal%22)) %7B%0A                        remotePrincipal = (Boolean) auth.getAttributes().get(%22remotePrincipal%22);%0A                        remotePrincipal = remotePrincipal == null ? Boolean.FALSE : remotePrincipal;%0A                    %7D
 %0A   
@@ -6125,16 +6125,16 @@
 ndpoint%0A
-
         
@@ -6152,16 +6152,41 @@
 rincipal
+ && institutionId != null
 ) %7B%0A    

Fix null pointer exception for remotePrincipal.