/**
 * 
 */
package org.ajax4jsf.application;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashSet;

import javax.faces.application.StateManager;
import javax.faces.component.UIColumn;
import javax.faces.component.UIComponent;
import javax.faces.component.UIData;
import javax.faces.component.UIInput;
import javax.faces.component.UIOutput;
import javax.faces.component.UIViewRoot;
import javax.faces.render.RenderKit;
import javax.faces.render.RenderKitFactory;

import org.ajax4jsf.application.AjaxStateManager.TreeStrutureNode;
import org.ajax4jsf.tests.AbstractAjax4JsfTestCase;


/**
 * @author asmirnov
 *
 */
public class AjaxStateManagerTest extends AbstractAjax4JsfTestCase {

	private static final String FACET_B = "facetB";
	private static final String FACET_A = "facetA";

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

	/* (non-Javadoc)
	 * @see org.ajax4jsf.tests.AbstractAjax4JsfTestCase#setUp()
	 */
	public void setUp() throws Exception {
		super.setUp();
	}

	/* (non-Javadoc)
	 * @see org.ajax4jsf.tests.AbstractAjax4JsfTestCase#tearDown()
	 */
	public void tearDown() throws Exception {
		super.tearDown();
	}

	/**
	 * Test method for {@link org.ajax4jsf.application.AjaxStateManager#restoreStateFromSession(javax.faces.context.FacesContext, java.lang.String, java.lang.String)}.
	 */
	public void testRestoreStateFromSession() {
//		fail("Not yet implemented");
	}

	/**
	 * Test method for {@link org.ajax4jsf.application.AjaxStateManager#getNextViewId(javax.faces.context.FacesContext)}.
	 */
	public void testGetNextViewId() {
//		fail("Not yet implemented");
	}

	/**
	 * Test method for {@link org.ajax4jsf.application.AjaxStateManager#getNumberOfViews(javax.faces.context.ExternalContext)}.
	 */
	public void testGetNumberOfViews() {
//		fail("Not yet implemented");
	}

	/**
	 * Test method for {@link org.ajax4jsf.application.AjaxStateManager#getRenderKit(javax.faces.context.FacesContext, java.lang.String)}.
	 */
	public void testGetRenderKit() {
		AjaxStateManager stateManager = getAjaxStateManager();
		RenderKit kit = stateManager.getRenderKit(facesContext, RenderKitFactory.HTML_BASIC_RENDER_KIT);
		assertSame(renderKit, kit);
	}
	
	public void testTreeNodeApply() throws Exception {
			buildTestTree();
			TreeStrutureNode node = new TreeStrutureNode();
			node.apply(facesContext, facesContext.getViewRoot(), new HashSet());
			assertEquals(2, node.getChildren().size());
			assertEquals(1, node.getFacets().size());
			TreeStrutureNode nodeA = (TreeStrutureNode) node.getFacets().get(FACET_A);
			assertNotNull(nodeA);
			assertEquals(1, nodeA.getChildren().size());
			assertEquals(1, nodeA.getFacets().size());
	}

	public void testTreeNodeCheckUniqueId() throws Exception {
		buildTestTree();
		TreeStrutureNode node = new TreeStrutureNode();
		UIViewRoot viewRoot = facesContext.getViewRoot();
		((UIComponent)viewRoot.getChildren().get(0)).setId(FACET_A);
		((UIComponent)viewRoot.getChildren().get(1)).setId(FACET_A);
		try {
			node.apply(facesContext, facesContext.getViewRoot(), new HashSet());
		} catch (IllegalStateException e) {
			assertTrue(e.getMessage().startsWith("duplicate"));
			return;
		}
		assertTrue("Duplicate components Id's not detected ",false);
	}
	
	
	public void testTreeNodeSerialisation() throws Exception {
		buildTestTree();
		TreeStrutureNode node = new TreeStrutureNode();
		node.apply(facesContext, facesContext.getViewRoot(), new HashSet());
		ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
		ObjectOutputStream out = new ObjectOutputStream(byteOut);
		out.writeObject(node);
		ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
		ObjectInputStream in = new ObjectInputStream(byteIn);
		TreeStrutureNode nodeIn = (TreeStrutureNode) in.readObject();
		assertEquals(2, nodeIn.getChildren().size());
		assertEquals(1, nodeIn.getFacets().size());
		TreeStrutureNode nodeA = (TreeStrutureNode) nodeIn.getFacets().get(FACET_A);
		assertNotNull(nodeA);
		assertEquals(1, nodeA.getChildren().size());
		assertEquals(1, nodeA.getFacets().size());
		
	}
	/**
	 * 
	 */
	private void buildTestTree() {
		facesContext.getViewRoot().getChildren().add(new UIInput());
		facesContext.getViewRoot().getChildren().add(new UIOutput());
		UIData data = new UIData();
		facesContext.getViewRoot().getFacets().put(FACET_A, data);
		data.getChildren().add(new UIColumn());
		data.getFacets().put(FACET_B, new UIOutput());
	}

	/**
	 * @return
	 */
	private AjaxStateManager getAjaxStateManager() {
		StateManager defaultStateManager = application.getStateManager();
		AjaxStateManager stateManager = new AjaxStateManager(defaultStateManager);
		return stateManager;
	}

}
