/**
 * License Agreement.
 *
 *  JBoss RichFaces - Ajax4jsf Component Library
 *
 * Copyright (C) 2007  Exadel, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 */

package org.richfaces.component;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.faces.component.UIForm;
import javax.faces.component.html.HtmlForm;
import javax.servlet.http.HttpServletResponse;

import org.ajax4jsf.resource.InternetResource;
import org.ajax4jsf.resource.InternetResourceBuilder;
import org.ajax4jsf.resource.ResourceBuilderImpl;
import org.ajax4jsf.resource.image.ImageInfo;
import org.ajax4jsf.tests.AbstractAjax4JsfTestCase;
import org.apache.commons.lang.StringUtils;
import org.richfaces.component.UIPanelMenu;
import org.richfaces.component.UIPanelMenuGroup;
import org.richfaces.component.UIPanelMenuItem;

import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlScript;

/**
 * Unit test for simple Component.
 */
public class PanelMenuComponentTest extends AbstractAjax4JsfTestCase {
	private static Set javaScripts = new HashSet();
	
	private String[] imageResources = new String[]{
            "org.richfaces.renderkit.html.iconimages.PanelMenuIconChevron",
            "org.richfaces.renderkit.html.iconimages.PanelMenuIconChevronDown",
            "org.richfaces.renderkit.html.iconimages.PanelMenuIconChevronUp",
            "org.richfaces.renderkit.html.iconimages.PanelMenuIconDisc",
            "org.richfaces.renderkit.html.iconimages.PanelMenuIconGrid",
            "org.richfaces.renderkit.html.iconimages.PanelMenuIconSpacer",
            "org.richfaces.renderkit.html.iconimages.PanelMenuIconTriangle",
            "org.richfaces.renderkit.html.iconimages.PanelMenuIconTriangleDown",
            "org.richfaces.renderkit.html.iconimages.PanelMenuIconTriangleUp"
    };
	
	static {
        javaScripts.add("org.ajax4jsf.javascript.AjaxScript");
        javaScripts.add("org.ajax4jsf.javascript.PrototypeScript");
        javaScripts.add("org/richfaces/renderkit/html/scripts/utils.js");
        javaScripts.add("org/richfaces/renderkit/html/scripts/panelMenu.js");
        javaScripts.add("org/ajax4jsf/javascript/scripts/form.js");
        javaScripts.add("org/richfaces/renderkit/html/scripts/form.js");
    }
	
    /**
     * Create the test case
     *
     * @param testName name of the test case
     */
    public PanelMenuComponentTest( String testName )
    {
        super( testName );
    }

    private UIForm form;
    private UIPanelMenu panelMenu;
    private UIPanelMenuGroup group1;
    private UIPanelMenuGroup group2;
    private UIPanelMenuGroup group3;
    private UIPanelMenuItem item1;
    private UIPanelMenuItem item2;
    
    public void setUp() throws Exception {
    	super.setUp();
    	
    	application.addComponent("org.richfaces.panelMenu", "org.richfaces.component.html.HtmlPanelMenu");
    	application.addComponent("org.richfaces.panelMenuGroup", "org.richfaces.component.html.HtmlPanelMenuGroup");
    	application.addComponent("org.richfaces.panelMenuItem", "org.richfaces.component.html.HtmlPanelMenuItem");
    	
    	form = new HtmlForm();
    	form.setId("form");
    	facesContext.getViewRoot().getChildren().add(form);
    	
    	panelMenu = (UIPanelMenu)application.createComponent("org.richfaces.panelMenu");
    	panelMenu.setId("panelMenu");
    	form.getChildren().add(panelMenu);
    	
    	group1 = (UIPanelMenuGroup)application.createComponent("org.richfaces.panelMenuGroup");
    	group1.setId("group1");
    	group1.setDisabled(true);
    	panelMenu.getChildren().add(group1);
    	
    	group2 = (UIPanelMenuGroup)application.createComponent("org.richfaces.panelMenuGroup");
    	group2.setId("group2");
    	panelMenu.getChildren().add(group2);
    	
    	item1 = (UIPanelMenuItem)application.createComponent("org.richfaces.panelMenuItem");
    	item1.setId("item1");
    	group1.getChildren().add(item1);
    	
    	group3 = (UIPanelMenuGroup)application.createComponent("org.richfaces.panelMenuGroup");
    	group3.setId("subgroup");
    	group2.getChildren().add(group3);
    	
    	item2 = (UIPanelMenuItem)application.createComponent("org.richfaces.panelMenuItem");
    	item2.setId("item2");
    	item2.setDisabled(true);
    	group2.getChildren().add(item2);
    	
    	// Items for testing standard icons.
    	UIPanelMenuItem item = (UIPanelMenuItem)application.createComponent("org.richfaces.panelMenuItem");
    	item.setId("triangleItem");
    	item.setIcon("triangle");
    	group2.getChildren().add(item);
    	
    	item = (UIPanelMenuItem)application.createComponent("org.richfaces.panelMenuItem");
    	item.setId("spacerItem");
    	item.setIcon("spacer");
    	group2.getChildren().add(item);
    	
    	item = (UIPanelMenuItem)application.createComponent("org.richfaces.panelMenuItem");
    	item.setId("triangleDownItem");
    	item.setIcon("triangleDown");
    	group2.getChildren().add(item);
    	
    	item = (UIPanelMenuItem)application.createComponent("org.richfaces.panelMenuItem");
    	item.setId("triangleUpItem");
    	item.setIcon("triangleUp");
    	group2.getChildren().add(item);
    	
    	item = (UIPanelMenuItem)application.createComponent("org.richfaces.panelMenuItem");
    	item.setId("chevronItem");
    	item.setIcon("chevron");
    	group2.getChildren().add(item);
    	
    	item = (UIPanelMenuItem)application.createComponent("org.richfaces.panelMenuItem");
    	item.setId("chevronUpItem");
    	item.setIcon("chevronUp");
    	group2.getChildren().add(item);
    	
    	item = (UIPanelMenuItem)application.createComponent("org.richfaces.panelMenuItem");
    	item.setId("chevronDownItem");
    	item.setIcon("chevronDown");
    	group2.getChildren().add(item);
    	
    	item = (UIPanelMenuItem)application.createComponent("org.richfaces.panelMenuItem");
    	item.setId("discItem");
    	item.setIcon("disc");
    	group2.getChildren().add(item);
    	
    	item = (UIPanelMenuItem)application.createComponent("org.richfaces.panelMenuItem");
    	item.setId("gridItem");
    	item.setIcon("grid");
    	group2.getChildren().add(item);
    	
    }
    
    public void tearDown() throws Exception {
    	super.tearDown();
    	
    	item1 = null;
    	item2 = null;
    	group1 = null;
    	group2 = null;
    	form = null;
    }
    
    /**
     * Test component rendering
     *
     * @throws Exception
     */
    public void testRender() throws Exception {
    	HtmlPage page = renderView();
        assertNotNull(page);
        System.out.println(page.asXml());
        
        HtmlElement div = page.getHtmlElementById(panelMenu.getClientId(facesContext));
        assertNotNull(div);
        assertEquals("div", div.getNodeName());
        
        HtmlElement firstGroupDiv = page.getHtmlElementById(group1.getClientId(facesContext));
        assertNotNull(firstGroupDiv);
        assertEquals("div", firstGroupDiv.getNodeName());
        
        String styleClass = firstGroupDiv.getAttributeValue("class");
        assertTrue(styleClass.contains("dr-pmenu-top-group-div"));
        
        HtmlElement firstGroupHide = page.getHtmlElementById("tablehide" + group1.getClientId(facesContext));
        assertNotNull(firstGroupHide);
        assertEquals("table", firstGroupHide.getNodeName());
        
        styleClass = firstGroupHide.getAttributeValue("class");
        assertTrue(styleClass.contains("dr-pmenu-top-group"));
        assertTrue(styleClass.contains("rich-pmenu-group"));
        assertTrue(styleClass.contains("rich-pmenu-disabled-element"));
        assertTrue(styleClass.contains("dr-pmenu-disabled-element"));
        
        HtmlElement subGroupDiv = page.getHtmlElementById(group3.getClientId(facesContext));
        assertNotNull(subGroupDiv);
        assertEquals("div", subGroupDiv.getNodeName());
        
        HtmlElement subGroupHide = page.getHtmlElementById("tablehide" + group3.getClientId(facesContext));
        assertNotNull(subGroupHide);
        assertEquals("table", subGroupHide.getNodeName());
        
        styleClass = subGroupHide.getAttributeValue("class");
        assertTrue(styleClass.contains("dr-pmenu-group"));
        assertTrue(styleClass.contains("rich-pmenu-group"));
        
        HtmlElement leftIcon = page.getHtmlElementById("leftIcon" + group1.getClientId(facesContext));
        assertNotNull(leftIcon);
        assertEquals("img", leftIcon.getNodeName());
        
        HtmlElement rightIcon = page.getHtmlElementById("rightIcon" + group1.getClientId(facesContext));
        assertNotNull(rightIcon);
        assertEquals("img", rightIcon.getNodeName());
        
        HtmlElement firstItemHide = page.getHtmlElementById("tablehide" + item1.getClientId(facesContext));
        assertNotNull(firstItemHide);
        assertEquals("table", firstItemHide.getNodeName());
        
        styleClass = firstItemHide.getAttributeValue("class");
        assertTrue(styleClass.contains("dr-pmenu-item"));
        assertTrue(styleClass.contains("rich-pmenu-item"));
        
        leftIcon = page.getHtmlElementById("leftIcon" + item1.getClientId(facesContext));
        assertNotNull(leftIcon);
        assertEquals("img", leftIcon.getNodeName());
        
        rightIcon = page.getHtmlElementById("rightIcon" + item1.getClientId(facesContext));
        assertNotNull(rightIcon);
        assertEquals("img", rightIcon.getNodeName());
        
        HtmlElement secondItemHide = page.getHtmlElementById("tablehide" + item2.getClientId(facesContext));
        assertNotNull(secondItemHide);
        assertEquals("table", secondItemHide.getNodeName());
        
        styleClass = secondItemHide.getAttributeValue("class");
        assertTrue(styleClass.contains("rich-pmenu-disabled-element"));
    }
    
    /**
     * Test style rendering
     *
     * @throws Exception
     */
    public void testRenderStyle() throws Exception {
    	HtmlPage view = renderView();
        assertNotNull(view);
        List links = view.getDocumentElement().getHtmlElementsByTagName("link");
        assertEquals(1, links.size());
        HtmlElement link = (HtmlElement) links.get(0);
        assertTrue(link.getAttributeValue("href").contains("css/panelMenu.xcss"));
        
        InternetResourceBuilder builder = ResourceBuilderImpl.getInstance();
        InternetResource resource = builder.getResource("org/richfaces/renderkit/html/css/panelMenu.xcss");
        assertNotNull(resource);
        String uri = "http:" + resource.getUri(facesContext, null);
        Page page = webClient.getPage(uri);
        assertTrue(page.getWebResponse().getStatusCode() == HttpServletResponse.SC_OK);
    }
    
    /**
     * Test script rendering
     *
     * @throws Exception
     */
    public void testRenderScript() throws Exception {
    	HtmlPage page = renderView();
        assertNotNull(page);
        List scripts = page.getDocumentElement().getHtmlElementsByTagName("script");
        for (Iterator it = scripts.iterator(); it.hasNext();) {
            HtmlScript item = (HtmlScript) it.next();
            String srcAttr = item.getSrcAttribute();

            if (StringUtils.isNotBlank(srcAttr)) {
                boolean found = false;
                for (Iterator srcIt = javaScripts.iterator(); srcIt.hasNext();)
                {
                    String src = (String) srcIt.next();

                    found = srcAttr.contains(src);
                    if (found) {
                        break;
                    }
                }

                assertTrue(found);
            }
        }
    }
    
    public void testRenderImages() throws Exception {
    	HtmlPage view = renderView();
        assertNotNull(view);
        
        InternetResourceBuilder builder = ResourceBuilderImpl.getInstance();
        
        for (int i = 0; i < imageResources.length; i++) {
            InternetResource resource = builder.getResource(imageResources[i]);
            assertNotNull(resource);
            String uri = "http:" + resource.getUri(facesContext, null);
            Page page = webClient.getPage(uri);
            assertTrue(page.getWebResponse().getStatusCode() == HttpServletResponse.SC_OK);
            ImageInfo info = new ImageInfo();
            info.setInput(page.getWebResponse().getContentAsStream());
            //image recognizable?
            assertTrue(info.check());
            assertEquals(ImageInfo.FORMAT_GIF, info.getFormat());
        }
    }
}
