/**
 * 
 */
package javax.portlet.faces;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.portlet.PortletException;
import javax.portlet.PortletMode;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;

import org.ajax4jsf.portlet.AbstractAjax4jsfPortletTestCase;

/**
 * @author asmirnov
 * 
 */
public class GenericPortletTest extends AbstractAjax4jsfPortletTestCase {

	private final class GenericFacesPortletExtension extends
			GenericFacesPortlet {
		boolean editProcessed = false;
		boolean viewProcessed = false;
		boolean helpProcessed = false;

		@Override
		protected void doEdit(RenderRequest request, RenderResponse response)
				throws PortletException, IOException {
			editProcessed = true;
		}

		@Override
		protected void doView(RenderRequest request, RenderResponse response)
				throws PortletException, IOException {
			viewProcessed = true;
		}

		@Override
		protected void doHelp(RenderRequest request, RenderResponse response)
				throws PortletException, IOException {
			helpProcessed = true;
		}
	}

	/**
	 * @param name
	 */
	public GenericPortletTest(String name) {
		super(name);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see junit.framework.TestCase#setUp()
	 */
	public void setUp() throws Exception {
		super.setUp();
		MockBridge.actionCount = 0;
		MockBridge.destroyCount = 0;
		MockBridge.initCount = 0;
		MockBridge.responseCount = 0;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see junit.framework.TestCase#tearDown()
	 */
	public void tearDown() throws Exception {
		super.tearDown();
	}

	/**
	 * Test method for {@link javax.portlet.faces.GenericFacesPortlet#destroy()}.
	 * 
	 * @throws PortletException
	 * @throws IOException
	 */
	public void testDestroy() throws PortletException, IOException {
		setupActionRequest();
		GenericFacesPortlet portlet = new GenericFacesPortlet();
		portletContext.setInitParameter("javax.portlet.faces.BridgeClassName",
				MockBridge.class.getName());
		portlet.init(portletConfig);
		MockBridge facesPortletBrige = (MockBridge) portlet
				.getFacesPortletBrige();
		assertEquals(true, facesPortletBrige.isInitialized());
		assertEquals(1, MockBridge.initCount);
		portlet.destroy();
		assertEquals(1, MockBridge.destroyCount);
		assertEquals(false, facesPortletBrige.isInitialized());

	}

	/**
	 * Test method for
	 * {@link javax.portlet.faces.GenericFacesPortlet#init(javax.portlet.PortletConfig)}.
	 * 
	 * @throws PortletException
	 */
	public void testInitPortletConfig() throws PortletException {
		portletConfig.addInitParameter(
				"javax.portlet.faces.preserveActionParams", "true");
		portletConfig.addInitParameter("javax.portlet.faces.renderPolicy",
				Bridge.BridgeRenderPolicy.NEVER_DELEGATE.toString());
		portletConfig.setPortletName("foo");
		portletContext.setInitParameter("javax.portlet.faces.BridgeClassName",
				MockBridge.class.getName());
		GenericFacesPortlet portlet = new GenericFacesPortlet();
		portlet.init(portletConfig);
		assertEquals(Boolean.TRUE, portletContext
				.getAttribute("javax.portlet.faces.foo.preserveActionParams"));
		assertEquals(Bridge.BridgeRenderPolicy.NEVER_DELEGATE, portletContext
				.getAttribute("javax.portlet.faces.foo.renderPolicy"));
	}

	/**
	 * Test method for
	 * {@link javax.portlet.faces.GenericFacesPortlet#doDispatch(javax.portlet.RenderRequest, javax.portlet.RenderResponse)}.
	 * 
	 * @throws PortletException
	 * @throws IOException
	 */
	public void testDoDispatchRenderRequestRenderResponse()
			throws PortletException, IOException {
		setupRenderRequest();
		GenericFacesPortletExtension portlet = new GenericFacesPortletExtension();
		portletContext.setInitParameter("javax.portlet.faces.BridgeClassName",
				MockBridge.class.getName());
		portletConfig.addInitParameter(
				"javax.portlet.faces.defaultViewId.view", "index.jsf");
		portlet.init(portletConfig);
		portlet.doDispatch(renderRequest, renderResponse);
		assertEquals(0, MockBridge.responseCount);
		assertFalse(portlet.helpProcessed);
		assertFalse(portlet.editProcessed);
		assertTrue(portlet.viewProcessed);
	}

	/**
	 * Test method for
	 * {@link javax.portlet.faces.GenericFacesPortlet#doDispatch(javax.portlet.RenderRequest, javax.portlet.RenderResponse)}.
	 * 
	 * @throws PortletException
	 * @throws IOException
	 */
	public void testDoDispatchRenderRequestRenderResponseEdit()
			throws PortletException, IOException {
		setupRenderRequest();
		GenericFacesPortletExtension portlet = new GenericFacesPortletExtension();
		portletContext.setInitParameter("javax.portlet.faces.BridgeClassName",
				MockBridge.class.getName());
		portletConfig.addInitParameter(
				"javax.portlet.faces.defaultViewId.edit", "index.jsf");
		renderRequest.mode = PortletMode.EDIT;
		portlet.init(portletConfig);
		portlet.doDispatch(renderRequest, renderResponse);
		assertEquals(0, MockBridge.responseCount);
		assertFalse(portlet.helpProcessed);
		assertTrue(portlet.editProcessed);
		assertFalse(portlet.viewProcessed);
	}

	/**
	 * Test method for
	 * {@link javax.portlet.faces.GenericFacesPortlet#doDispatch(javax.portlet.RenderRequest, javax.portlet.RenderResponse)}.
	 * 
	 * @throws PortletException
	 * @throws IOException
	 */
	public void testDoDispatchRenderRequestRenderResponseHelp()
			throws PortletException, IOException {
		setupRenderRequest();
		GenericFacesPortletExtension portlet = new GenericFacesPortletExtension();
		portletContext.setInitParameter("javax.portlet.faces.BridgeClassName",
				MockBridge.class.getName());
		portletConfig.addInitParameter(
				"javax.portlet.faces.defaultViewId.view", "index.jsf");
		renderRequest.mode = PortletMode.HELP;
		portlet.init(portletConfig);
		portlet.doDispatch(renderRequest, renderResponse);
		assertEquals(0, MockBridge.responseCount);
		assertTrue(portlet.helpProcessed);
		assertFalse(portlet.editProcessed);
		assertFalse(portlet.viewProcessed);
	}

	/**
	 * Test method for
	 * {@link javax.portlet.faces.GenericFacesPortlet#doEdit(javax.portlet.RenderRequest, javax.portlet.RenderResponse)}.
	 * 
	 * @throws IOException
	 * @throws PortletException
	 */
	public void testDoEditRenderRequestRenderResponse()
			throws PortletException, IOException {
		setupRenderRequest();
		GenericFacesPortlet portlet = new GenericFacesPortlet();
		portletContext.setInitParameter("javax.portlet.faces.BridgeClassName",
				MockBridge.class.getName());
		portletConfig.addInitParameter(
				"javax.portlet.faces.defaultViewId.view", "index.jsf");
		renderRequest.mode = PortletMode.EDIT;
		portlet.init(portletConfig);
		portlet.doDispatch(renderRequest, renderResponse);
		assertEquals(0, MockBridge.responseCount);
	}

	/**
	 * Test method for
	 * {@link javax.portlet.faces.GenericFacesPortlet#doHelp(javax.portlet.RenderRequest, javax.portlet.RenderResponse)}.
	 */
	public void testDoHelpRenderRequestRenderResponse() {
		// fail("Not yet implemented");
	}

	/**
	 * Test method for
	 * {@link javax.portlet.faces.GenericFacesPortlet#doView(javax.portlet.RenderRequest, javax.portlet.RenderResponse)}.
	 * 
	 * @throws PortletException
	 * @throws IOException
	 */
	public void testDoViewRenderRequestRenderResponse()
			throws PortletException, IOException {
		setupRenderRequest();
		GenericFacesPortlet portlet = new GenericFacesPortlet();
		portletContext.setInitParameter("javax.portlet.faces.BridgeClassName",
				MockBridge.class.getName());
		portletConfig.addInitParameter(
				"javax.portlet.faces.defaultViewId.view", "index.jsf");
		portlet.init(portletConfig);
		portlet.doDispatch(renderRequest, renderResponse);
		assertEquals(1, MockBridge.responseCount);
	}

	/**
	 * Test method for
	 * {@link javax.portlet.faces.GenericFacesPortlet#processAction(javax.portlet.ActionRequest, javax.portlet.ActionResponse)}.
	 * 
	 * @throws PortletException
	 * @throws IOException
	 */
	public void testProcessActionActionRequestActionResponse()
			throws PortletException, IOException {
		setupActionRequest();
		GenericFacesPortlet portlet = new GenericFacesPortlet();
		portletContext.setInitParameter("javax.portlet.faces.BridgeClassName",
				MockBridge.class.getName());
		portletConfig.addInitParameter(
				"javax.portlet.faces.defaultViewId.view", "index.jsf");
		portlet.init(portletConfig);
		portlet.processAction(actionRequest, actionResponse);
		assertEquals(1, MockBridge.actionCount);
	}

	/**
	 * Test method for
	 * {@link javax.portlet.faces.GenericFacesPortlet#getBrigeClassName()}.
	 * 
	 * @throws PortletException
	 */
	public void testGetBrigeClassName() throws PortletException {
		setupActionRequest();
		GenericFacesPortlet portlet = new GenericFacesPortlet();
		portletContext.setInitParameter("javax.portlet.faces.BridgeClassName",
				MockBridge.class.getName());
		portletContext.setInitParameter(
				"javax.portlet.faces.defaultViewId.view", "index.jsf");
		portlet.init(portletConfig);
		assertEquals(MockBridge.class.getName(), portlet.getBrigeClassName());
	}

	/**
	 * Test method for
	 * {@link javax.portlet.faces.GenericFacesPortlet#getBrigeClassName()}.
	 * 
	 * @throws PortletException
	 */
	public void testGetBrigeClassName1() throws PortletException {
		setupActionRequest();
		GenericFacesPortlet portlet = new GenericFacesPortlet();
		try {
			portlet.init(portletConfig);

		} catch (PortletException e) {
			assertEquals("Can't detect bridge implementation class name", e
					.getMessage());
			return;
		}
		assertTrue("No exception for unknown bridge implementation", false);
	}

	/**
	 * Test method for
	 * {@link javax.portlet.faces.GenericFacesPortlet#getBrigeClassName()}.
	 * 
	 * @throws PortletException
	 */
	public void testGetBrigeClassName2() throws PortletException {
		ClassLoader loader = Thread.currentThread().getContextClassLoader();
		ClassLoader testLoader = new ClassLoader(loader) {
			@Override
			public InputStream getResourceAsStream(String name) {
				if ("META-INF/services/javax.portlet.faces.Bridge".equals(name)) {
					return new ByteArrayInputStream("foo.bar.Bridge".getBytes());
				}
				return super.getResourceAsStream(name);
			}
		};
		try {
			Thread.currentThread().setContextClassLoader(testLoader);
			setupActionRequest();
			GenericFacesPortlet portlet = new GenericFacesPortlet();
			portlet.init(portletConfig);
			assertEquals("foo.bar.Bridge", portlet.getBrigeClassName());

		} finally {
			Thread.currentThread().setContextClassLoader(loader);
		}
	}

	/**
	 * Test method for
	 * {@link javax.portlet.faces.GenericFacesPortlet#getDefaultViewId(javax.portlet.PortletRequest, javax.portlet.PortletMode)}.
	 * 
	 * @throws PortletException
	 */
	public void testGetDefaultViewId() throws PortletException {
		setupActionRequest();
		GenericFacesPortlet portlet = new GenericFacesPortlet();
		portletContext.setInitParameter("javax.portlet.faces.BridgeClassName",
				MockBridge.class.getName());
		portletConfig.addInitParameter(
				"javax.portlet.faces.defaultViewId.view", "index.jsf");
		portlet.init(portletConfig);
		assertEquals("index.jsf", portlet.getDefaultViewId(actionRequest,
				actionRequest.getPortletMode()));
	}

	/**
	 * Test method for
	 * {@link javax.portlet.faces.GenericFacesPortlet#getFacesPortletBrige()}.
	 * 
	 * @throws PortletException
	 */
	public void testGetFacesPortletBrige() throws PortletException {
		setupActionRequest();
		GenericFacesPortlet portlet = new GenericFacesPortlet();
		portletContext.setInitParameter("javax.portlet.faces.BridgeClassName",
				MockBridge.class.getName());
		portlet.init(portletConfig);
		MockBridge facesPortletBrige = (MockBridge) portlet
				.getFacesPortletBrige();
		assertEquals(true, facesPortletBrige.isInitialized());
	}

}
