package com.avaya.zephyr.services.sample_services.Authorization.TaskDashboard.filter;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

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 org.apache.http.client.utils.URIBuilder;

import com.avaya.collaboration.businessdata.api.NoAttributeFoundException;
import com.avaya.collaboration.businessdata.api.ServiceData;
import com.avaya.collaboration.businessdata.api.ServiceNotFoundException;
import com.avaya.collaboration.dal.factory.CollaborationDataFactory;
import com.avaya.collaboration.util.logger.Logger;
import com.avaya.zephyr.platform.dal.api.ServiceUtil;
import com.avaya.zephyr.services.sample_services.Authorization.util.ServiceAttributeStore;

public class ResourceOwnerCredentialsFilter implements Filter
{
    private final ServiceData serviceData;

    private final Logger logger;

    public ResourceOwnerCredentialsFilter()
    {
        this(CollaborationDataFactory.getServiceData(ServiceUtil.getServiceDescriptor().getName(),
                ServiceUtil.getServiceDescriptor().getVersion()),
                Logger.getLogger(ResourceOwnerCredentialsFilter.class));
    }

    ResourceOwnerCredentialsFilter(final ServiceData serviceData, final Logger logger)
    {
        this.serviceData = serviceData;
        this.logger = logger;
    }

    @Override
    public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain)
            throws IOException, ServletException
    {
        if (hasSessionCookie(servletRequest))
        {
            logger.finer("ResourceOwnerCredentialsFilter: cookie present, calling doFilter()");
            filterChain.doFilter(servletRequest, servletResponse);
        }
        else if (isGrantTypeResourceOwner())
        {
            redirectToDashboardLoginPage(servletRequest, servletResponse);
        }
        else
        {
            filterChain.doFilter(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 void redirectToDashboardLoginPage(final ServletRequest servletRequest,
            final ServletResponse servletResponse) throws IOException, ServletException
    {

        final HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        final HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
        try
        {
            final URI loginPageUri = new URIBuilder()
                    .setScheme(httpServletRequest.getHeader("Scheme"))
                    .setHost(httpServletRequest.getHeader("Host"))
                    .setPath("/services/TaskDashboard/")
                    .build();

            httpServletResponse.sendRedirect(loginPageUri.toString());
        }
        catch (final URISyntaxException e)
        {
            logger.warn("RedirectToDashboard caught exception: " + e);
        }
    }

    private boolean isGrantTypeResourceOwner()
    {
        try
        {
            final String authenticationMechanism = serviceData.getServiceAttribute("com.avaya.authorization.grantType");
            if (!StringUtils.isBlank(authenticationMechanism))
            {
                return authenticationMechanism.equalsIgnoreCase("ResourceOwner");
            }
        }
        catch (NoAttributeFoundException | ServiceNotFoundException e)
        {
            logger.warn("Caught exception while retrieving grant type service attribute", e);
        }
        return false;
    }

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

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