/****************************************************************************
 * 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.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;

import com.avaya.collaboration.authorization.AuthorizationHelperException;
import com.avaya.collaboration.authorization.client.AccessToken;
import com.avaya.collaboration.authorization.client.AuthorizationClientHelper;
import com.avaya.collaboration.authorization.client.HttpResponseException;
import com.avaya.collaboration.util.logger.Logger;
import com.avaya.zephyr.services.sample_services.Authorization.http.HttpRequestHeaderAdder;

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

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

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

    @Override
    public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain)
            throws IOException, ServletException
    {
        if (hasAuthorizationCode(servletRequest))
        {
            fetchAccessTokenAndDoFilter(servletRequest, servletResponse, filterChain);
        }
        else
        {
            logger.warn("Request not authenticated - no authorization code found.");
            ((HttpServletResponse) servletResponse).sendError(HttpServletResponse.SC_UNAUTHORIZED, "No authorization code");
        }
    }

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

    private void fetchAccessTokenAndDoFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
            final FilterChain filterChain) throws IOException, ServletException
    {
        final HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        try
        {
            final AccessToken accessToken = AuthorizationClientHelper.getAccessTokenForUser(servletRequest);

            final HttpRequestHeaderAdder httpRequestHeaderAdder = new HttpRequestHeaderAdder(httpServletRequest);
            httpRequestHeaderAdder.addHeader("Authorization", "Bearer " + accessToken.toString());

            logger.finer("AccessTokenHeaderFilter: calling doFilter()");
            filterChain.doFilter(httpRequestHeaderAdder, servletResponse);
        }
        catch (AuthorizationHelperException | HttpResponseException e)
        {
            logger.warn("ProcessAuthorizationCode caught exception: " + e);
            ((HttpServletResponse) servletResponse).sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
        }
    }

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

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