package com.google.inject.servlet;

import com.google.inject.Binding;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.internal.util.Maps;
import com.google.inject.internal.util.Sets;
import com.google.inject.spi.BindingScopingVisitor;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import junit.framework.TestCase;
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;

/**
 * Tests the lifecycle of the encapsulated {@link FilterDefinition} class.
 *
 * @author Dhanji R. Prasanna (dhanji@gmail com)
 */
public class FilterDefinitionTest extends TestCase {

  public final void testFilterInitAndConfig() throws ServletException {

    Injector injector = createMock(Injector.class);
    Binding binding = createMock(Binding.class);

    final MockFilter mockFilter = new MockFilter();

    expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject()))
        .andReturn(true);
    expect(injector.getBinding(Key.get(Filter.class)))
        .andReturn(binding);

    expect(injector.getInstance(Key.get(Filter.class)))
        .andReturn(mockFilter)
        .anyTimes();

    replay(binding, injector);

    //some init params
    //noinspection SSBasedInspection
    final Map<String, String> initParams = new HashMap<String, String>() {{
      put("ahsd", "asdas24dok");
      put("ahssd", "asdasd124ok");
      put("ahfsasd", "asda124sdok");
      put("ahsasgd", "a124sdasdok");
      put("ahsd124124", "as124124124dasdok");
    }};

    String pattern = "/*";
    final FilterDefinition filterDef = new FilterDefinition(pattern, Key.get(Filter.class),
        UriPatternType.get(UriPatternType.SERVLET, pattern), initParams);
    assert filterDef.getFilter() instanceof MockFilter;

    ServletContext servletContext = createMock(ServletContext.class);
    final String contextName = "thing__!@@44";
    expect(servletContext.getServletContextName()).andReturn(contextName);

    replay(servletContext);

    filterDef.init(servletContext, injector,
        Sets.newSetFromMap(Maps.<Filter, Boolean>newIdentityHashMap()));

    final FilterConfig filterConfig = mockFilter.getConfig();
    assert null != filterConfig;
    assert contextName.equals(filterConfig.getServletContext().getServletContextName());
    assert Key.get(Filter.class).toString().equals(filterConfig.getFilterName());

    final Enumeration names = filterConfig.getInitParameterNames();
    while (names.hasMoreElements()) {
      String name = (String) names.nextElement();

      assert initParams.containsKey(name);
      assert initParams.get(name).equals(filterConfig.getInitParameter(name));
    }
  }

  public final void testFilterCreateDispatchDestroy() throws ServletException, IOException {
    Injector injector = createMock(Injector.class);
    Binding binding = createMock(Binding.class);
    HttpServletRequest request = createMock(HttpServletRequest.class);

    final MockFilter mockFilter = new MockFilter();

    expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject()))
        .andReturn(true);
    expect(injector.getBinding(Key.get(Filter.class)))
        .andReturn(binding);

    expect(injector.getInstance(Key.get(Filter.class)))
        .andReturn(mockFilter)
        .anyTimes();

    expect(request.getServletPath()).andReturn("/index.html");

    replay(injector, binding, request);

    String pattern = "/*";
    final FilterDefinition filterDef = new FilterDefinition(pattern, Key.get(Filter.class),
        UriPatternType.get(UriPatternType.SERVLET, pattern), new HashMap<String, String>());
    assert filterDef.getFilter() instanceof MockFilter;

    //should fire on mockfilter now
    filterDef.init(createMock(ServletContext.class), injector,
        Sets.newSetFromMap(Maps.<Filter, Boolean>newIdentityHashMap()));

    assert mockFilter.isInit() : "Init did not fire";

    final boolean proceed[] = new boolean[1];
    filterDef.doFilter(request, null, new FilterChainInvocation(null, null, null) {
      public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse)
          throws IOException, ServletException {

        proceed[0] = true;
      }
    });

    assertTrue("Filter did not proceed down chain", proceed[0]);

    filterDef.destroy(Sets.newSetFromMap(Maps.<Filter, Boolean>newIdentityHashMap()));
    assertTrue("Destroy did not fire", mockFilter.isDestroy());

    verify(injector, request);

  }

  public final void testFilterCreateDispatchDestroySupressChain()
      throws ServletException, IOException {

    Injector injector = createMock(Injector.class);
    Binding binding = createMock(Binding.class);
    HttpServletRequest request = createMock(HttpServletRequest.class);

    final MockFilter mockFilter = new MockFilter() {
      public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
          FilterChain filterChain) throws IOException, ServletException {
        setRun(true);

        //suppress rest of chain...
      }
    };

    expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject()))
        .andReturn(true);
    expect(injector.getBinding(Key.get(Filter.class)))
        .andReturn(binding);
    
    expect(injector.getInstance(Key.get(Filter.class)))
        .andReturn(mockFilter)
        .anyTimes();

    expect(request.getServletPath()).andReturn("/index.html");

    replay(injector, binding, request);

    String pattern = "/*";
    final FilterDefinition filterDef = new FilterDefinition(pattern, Key.get(Filter.class),
        UriPatternType.get(UriPatternType.SERVLET, pattern), new HashMap<String, String>());
    assert filterDef.getFilter() instanceof MockFilter;

    //should fire on mockfilter now
    filterDef.init(createMock(ServletContext.class), injector,
        Sets.newSetFromMap(Maps.<Filter, Boolean>newIdentityHashMap()));

    assert mockFilter.isInit() : "Init did not fire";

    final boolean proceed[] = new boolean[1];
    filterDef.doFilter(request, null, new FilterChainInvocation(null, null, null) {
      public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse)
          throws IOException, ServletException {
        proceed[0] = true;
      }
    });

    assert !proceed[0] : "Filter did not suppress chain";

    filterDef.destroy(Sets.newSetFromMap(Maps.<Filter, Boolean>newIdentityHashMap()));
    assert mockFilter.isDestroy() : "Destroy did not fire";

    verify(injector, request);

  }

  private static class MockFilter implements Filter {
    private boolean init;
    private boolean destroy;
    private boolean run;
    private FilterConfig config;

    public void init(FilterConfig filterConfig) throws ServletException {
      init = true;

      this.config = filterConfig;
    }

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
        FilterChain filterChain) throws IOException, ServletException {
      run = true;

      //proceed
      filterChain.doFilter(servletRequest, servletResponse);
    }

    protected void setRun(boolean run) {
      this.run = run;
    }

    public void destroy() {
      destroy = true;
    }

    public boolean isInit() {
      return init;
    }

    public boolean isDestroy() {
      return destroy;
    }

    public boolean isRun() {
      return run;
    }

    public FilterConfig getConfig() {
      return config;
    }
  }
}
