package gov.va.med.edp.springframework.security.ui.vistalink;

import gov.va.med.edp.springframework.security.providers.vistalink.VistaAuthenticationToken;
import gov.va.med.edp.springframework.security.userdetails.vistalink.VistaUser;
import junit.framework.TestCase;
import org.springframework.security.Authentication;
import org.springframework.security.AuthenticationManager;
import org.springframework.security.GrantedAuthority;
import org.easymock.MockControl;
import org.easymock.AbstractMatcher;
import org.springframework.mock.web.MockFilterChain;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;

public class VistaAuthenticationProcessingFilterTest extends TestCase {

    private MockHttpServletRequest request = new MockHttpServletRequest();
    private MockHttpServletResponse response = new MockHttpServletResponse();
    private MockFilterChain filterChain = new MockFilterChain();

    private MockControl mockAuthenticationManagerControl;
    private AuthenticationManager mockAuthenticationManager;

    protected void setUp() throws Exception {
        mockAuthenticationManagerControl = MockControl.createControl(AuthenticationManager.class);
        mockAuthenticationManager = (AuthenticationManager) mockAuthenticationManagerControl.getMock();
    }

    public void testAttemptAuthentication() throws Exception {
        VistaAuthenticationProcessingFilter f = new VistaAuthenticationProcessingFilter();
        f.setDefaultTargetUrl("/welcome.jsp");
        f.setAuthenticationFailureUrl("/authenticationFailed.jsp");
        f.setAuthenticationManager(mockAuthenticationManager);
        f.afterPropertiesSet();

        request.addParameter(VistaAuthenticationProcessingFilter.STATION_NUMBER_KEY, "983A");
        request.addParameter(VistaAuthenticationProcessingFilter.ACCESS_CODE_KEY, "10VEHU");
        request.addParameter(VistaAuthenticationProcessingFilter.VERIFY_CODE_KEY, "VEHU10");
        request.setRemoteAddr("10.0.1.34");
        request.setRequestURI(f.getFilterProcessesUrl());

        VistaAuthenticationToken authRequest = new VistaAuthenticationToken("983A", "10VEHU", "VEHU10", "10.0.1.34");
        mockAuthenticationManager.authenticate(authRequest);
        mockAuthenticationManagerControl.setMatcher(new AuthenticationEquals());
        mockAuthenticationManagerControl.setReturnValue(new VistaAuthenticationToken(new VistaUser("54321.123456789", "983A", "12345", "10VEHU", "VEHU10", "Vehu,Ten", "Ten Vehu", "TEN", null, "VEHU", null, null, null, true, true, true, true, new GrantedAuthority[]{}), "10VEHU", "VEHU10", "10.0.1.34", new GrantedAuthority[]{}));       
        mockAuthenticationManagerControl.replay();

        f.doFilter(request, response, filterChain);

        assertNull(filterChain.getRequest());
        assertNull(filterChain.getResponse());

        mockAuthenticationManagerControl.verify();
    }

    static class AuthenticationEquals extends AbstractMatcher {

        protected boolean argumentMatches(Object o, Object o1) {
            if (!(o instanceof Authentication)) return false;
            if (!(o1 instanceof Authentication)) return false;
            Authentication expected = (Authentication) o;
            Authentication actual = (Authentication) o1;
            return expected.getPrincipal().equals(actual.getPrincipal()) &&
                    expected.getName().equals(actual.getName()) &&
                    expected.getCredentials().equals(actual.getCredentials()) &&
                    expected.getDetails().equals(actual.getDetails()) &&
                    expected.isAuthenticated() == actual.isAuthenticated();
        }
    }
}

/* version for java 5 and later easymock
import gov.va.med.edp.springframework.security.providers.vistalink.VistaAuthenticationToken;
import gov.va.med.edp.springframework.security.ui.vistalink.VistaAuthenticationProcessingFilter;
import gov.va.med.edp.springframework.security.userdetails.vistalink.VistaUser;
import junit.framework.TestCase;
import org.springframework.security.Authentication;
import org.springframework.security.AuthenticationManager;
import org.springframework.security.GrantedAuthority;
import org.easymock.EasyMock;
import static org.easymock.EasyMock.*;
import org.easymock.IArgumentMatcher;
import org.springframework.mock.web.MockFilterChain;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;

public class VistaAuthenticationProcessingFilterTest extends TestCase {

    private MockHttpServletRequest request = new MockHttpServletRequest();
    private MockHttpServletResponse response = new MockHttpServletResponse();
    private MockFilterChain filterChain = new MockFilterChain();
    private AuthenticationManager mockAuthenticationManager;

    protected void setUp() throws Exception {
        mockAuthenticationManager = createMock(AuthenticationManager.class);
    }

    public void testAttemptAuthentication() throws Exception {
        VistaAuthenticationProcessingFilter f = new VistaAuthenticationProcessingFilter();
        f.setDefaultTargetUrl("/welcome.jsp");
        f.setAuthenticationFailureUrl("/authenticationFailed.jsp");
        f.setAuthenticationManager(mockAuthenticationManager);
        f.afterPropertiesSet();

        request.addParameter(VistaAuthenticationProcessingFilter.STATION_NUMBER_KEY, "983A");
        request.addParameter(VistaAuthenticationProcessingFilter.ACCESS_CODE_KEY, "10VEHU");
        request.addParameter(VistaAuthenticationProcessingFilter.VERIFY_CODE_KEY, "VEHU10");
        request.setRemoteAddr("10.0.1.34");
        request.setRequestURI(f.getFilterProcessesUrl());

        VistaAuthenticationToken authRequest = new VistaAuthenticationToken("983A", "10VEHU", "VEHU10", "10.0.1.34");
        expect(mockAuthenticationManager.authenticate(eqAuth(authRequest))).andReturn(new VistaAuthenticationToken(new VistaUser("54321.123456789", "983A", "12345", "10VEHU", "VEHU10", "Vehu,Ten", "Ten Vehu", "TEN", null, "VEHU", null, null, null, true, true, true, true, new GrantedAuthority[]{}), "10VEHU", "VEHU10", "10.0.1.34", new GrantedAuthority[]{}));
        replay(mockAuthenticationManager);

        f.doFilter(request, response, filterChain);

        assertNull(filterChain.getRequest());
        assertNull(filterChain.getResponse());

        verify(mockAuthenticationManager);
    }

    static class AuthenticationEquals implements IArgumentMatcher {

        private Authentication expected;

        public AuthenticationEquals(Authentication expected) {
            this.expected = expected;
        }

        public boolean matches(Object o) {
            if (!(o instanceof Authentication)) return false;

            Authentication actual = (Authentication) o;

            return expected.getPrincipal().equals(actual.getPrincipal()) &&
                    expected.getName().equals(actual.getName()) &&
                    expected.getCredentials().equals(actual.getCredentials()) &&
                    expected.getDetails().equals(actual.getDetails()) &&
                    expected.isAuthenticated() == actual.isAuthenticated();
        }

        public void appendTo(StringBuffer stringBuffer) {
            //To change body of implemented methods use File | Settings | File Templates.
        }
    }

    public static <T extends Authentication> T eqAuth(T in) {
        EasyMock.reportMatcher(new AuthenticationEquals(in));
        return null;
    }
}
*/