/****************************************************************************
 * Copyright Avaya Inc., All Rights Reserved.
 * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF Avaya Inc.
 * The copyright notice above does not evidence any actual or intended publication of such source code.
 * Some third-party source code components may have been modified from their original versions by Avaya Inc.
 * The modifications are Copyright Avaya Inc., All Rights Reserved.
 * Avaya Confidential & Restricted. May not be distributed further without written permission of
 * the Avaya owner.
 ****************************************************************************/
package com.avaya.zephyr.services.sample_services.Authorization;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;

import com.avaya.collaboration.authorization.AuthorizationHelperException;
import com.avaya.collaboration.authorization.client.AuthorizationClientHelper;
import com.avaya.collaboration.util.logger.Logger;
import com.avaya.zephyr.services.sample_services.Authorization.util.ServiceAttributeStore;

public class AuthorizationCodeFilter implements Filter
{
    private static final String AUTH_CODE_GRANT_TYPE = "code";
    private final Logger logger;

    public AuthorizationCodeFilter()
    {
        this(Logger.getLogger(AuthorizationCodeFilter.class));
    }

    AuthorizationCodeFilter(final Logger logger)
    {
        this.logger = logger;
    }

    @Override
    public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
            final FilterChain filterChain) throws IOException, ServletException
    {
        if (hasSessionCookie(servletRequest))
        {
            logger.finer("AuthorizationCodeGrantFilter: cookie present, calling doFilter()");
            filterChain.doFilter(servletRequest, servletResponse);
        }
        else if (hasAuthorizationCode(servletRequest))
        {
            logger.finer("AuthorizationCodeGrantFilter: auth code present, calling doFilter()");
            filterChain.doFilter(servletRequest, servletResponse);
        }
        else
        {
            logger.finer("AuthorizationCodeGrantFilter: redirecting to get auth code");
            redirectToFetchAuthCode(servletRequest, servletResponse);
        }
    }

    private boolean hasSessionCookie(ServletRequest servletRequest)
    {
        final HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        final Cookie[] cookies = httpServletRequest.getCookies();
        if (cookies != null && cookies.length > 0)
        {
            for (int i = 0; i < cookies.length; i++)
            {
                if (cookies[i].getName().equals(ServiceAttributeStore.getInstance().getSessionCookieName()))
                {
                    return true;
                }
            }
            return false;
        }
        else
        {
            return false;
        }
    }

    private boolean hasAuthorizationCode(final ServletRequest servletRequest)
    {
        return StringUtils.isNotBlank(servletRequest.getParameter(AUTH_CODE_GRANT_TYPE));
    }

    private void redirectToFetchAuthCode(final ServletRequest servletRequest, final ServletResponse servletResponse) throws IOException
    {
        final HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;

        try
        {
            final String authorizationEndpoint = AuthorizationClientHelper.getAuthorizationEndpoint(servletRequest);
            httpResponse.sendRedirect(authorizationEndpoint);
        }
        catch (final AuthorizationHelperException e)
        {
            logger.warn("RedirectRequestToAuthorization caught exception: " + e);
            ((HttpServletResponse) servletResponse).sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
        }
    }

    @Override
    public void init(final FilterConfig filterConfig) throws ServletException
    {
        logger.finer("AuthorizationCodeGrantFilter : init");
    }

    @Override
    public void destroy()
    {
        logger.finer("AuthorizationCodeGrantFilter : destroy");
    }
}
