package org.codehaus.groovy.grails.web.servlet;

import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;
import junit.framework.TestCase;

import org.codehaus.groovy.grails.commons.ControllerArtefactHandler;
import org.codehaus.groovy.grails.commons.DefaultGrailsApplication;
import org.codehaus.groovy.grails.commons.GrailsApplication;
import org.codehaus.groovy.grails.commons.GrailsClass;
import org.codehaus.groovy.grails.commons.TagLibArtefactHandler;
import org.codehaus.groovy.grails.support.MockApplicationContext;
import org.codehaus.groovy.grails.web.metaclass.ControllerDynamicMethods;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockServletContext;

public class GrailsApplicationAttributesTests extends TestCase {

    /*
     * Test method for 'org.codehaus.groovy.grails.web.servlet.DefaultGrailsApplicationAttributes.getTemplateUri(String, ServletRequest)'
     */
    public void testGetTemplateUri() {
         GrailsApplicationAttributes attrs = new DefaultGrailsApplicationAttributes(new MockServletContext());

         assertEquals("/_test.gsp",attrs.getTemplateUri("/test", new MockHttpServletRequest()));
         assertEquals("/shared/_test.gsp",attrs.getTemplateUri("/shared/test", new MockHttpServletRequest()));
    }

    /*
     * Test method for 'org.codehaus.groovy.grails.web.servlet.DefaultGrailsApplicationAttributes.getViewUri(String, ServletRequest)'
     */
    public void testGetViewUri() throws Exception {
        GrailsApplicationAttributes attrs = new DefaultGrailsApplicationAttributes(new MockServletContext());
        GroovyClassLoader gcl = new GroovyClassLoader();
        Class<?> controllerClass = gcl.parseClass( "class TestController {\n" +
                "def "+ControllerDynamicMethods.CONTROLLER_URI_PROPERTY+" = '/test'\n" +
                "def "+ControllerDynamicMethods.CONTROLLER_NAME_PROPERTY+" = 'test'\n" +
                "}" );

        MockHttpServletRequest request = new MockHttpServletRequest();
        request.setAttribute(GrailsApplicationAttributes.CONTROLLER, controllerClass.newInstance());

        assertEquals("/WEB-INF/grails-app/views/test/aView.gsp",attrs.getViewUri("aView", request));
        assertEquals("/WEB-INF/grails-app/views/shared.gsp",attrs.getViewUri("/shared", request));
    }

    public void testGetTagLibForTag() throws Exception {
        GroovyClassLoader gcl = new GroovyClassLoader();
        gcl.parseClass( "class TestController {\n" +
                                                    "def list = {\n" +
                                                    "}\n" +
                                                    "}\n" +
                         "class FirstTagLib {\n" +
                                      "def firstTag = {\n" +
                                      "}\n" +
                         "}\n" +
                         "class SecondTagLib {\n" +
                             "def secondTag = {\n" +
                         "}\n" +
                "}" );

        GrailsApplicationAttributes attrs = getAttributesForClasses(gcl.getLoadedClasses(),gcl);
        assertNotNull(attrs);
        assertNotNull(attrs.getApplicationContext());
        assertNotNull(attrs.getGrailsApplication());

        MockHttpServletRequest request = new MockHttpServletRequest();
        MockHttpServletResponse response = new MockHttpServletResponse();
        GroovyObject controller = (GroovyObject)attrs.getApplicationContext().getBean("TestController");
        request.setAttribute(GrailsApplicationAttributes.CONTROLLER,controller );
        GroovyObject tagLib1 = attrs.getTagLibraryForTag(request,response,"firstTag");
        assertNotNull(tagLib1);
    }

    private GrailsApplicationAttributes getAttributesForClasses(Class<?>[] classes, GroovyClassLoader gcl) {
        MockApplicationContext context = new MockApplicationContext();
        MockServletContext servletContext = new MockServletContext();
        servletContext.setAttribute(GrailsApplicationAttributes.APPLICATION_CONTEXT,context);

        GrailsApplication app = new DefaultGrailsApplication(classes,gcl);
        app.initialise();
        context.registerMockBean(GrailsApplication.APPLICATION_ID,app);

        GrailsClass[] controllers = app.getArtefacts(ControllerArtefactHandler.TYPE);
        for (int i = 0; i < controllers.length; i++) {
            context.registerMockBean(controllers[i].getFullName(), controllers[i].newInstance());
        }

        GrailsClass[] taglibs = app.getArtefacts(TagLibArtefactHandler.TYPE);
        for (int i = 0; i < taglibs.length; i++) {
            context.registerMockBean(taglibs[i].getFullName(), taglibs[i].newInstance());
        }
        return new DefaultGrailsApplicationAttributes(servletContext);
    }
}
