/*
 * DataScrollerTest.java		Date created: 29.09.2008
 * Last modified by: $Author$
 * $Revision$	$Date$
 */

package org.richfaces.testng;

import java.util.ArrayList;
import java.util.List;

import org.ajax4jsf.template.Template;
import org.richfaces.AutoTester;
import org.richfaces.SeleniumTestBase;
import org.testng.Assert;
import org.testng.annotations.Test;

/**
 * DataScroller selenium test class
 * @author Andrey Markavtsov
 *
 */
public class DataScrollerTest extends SeleniumTestBase {
	
	static String TEST__URL = "pages/dataScroller/dataScroller.xhtml";
	
	static final String RESET_METHOD_ME = "#{dataScrollerBean.reset}";
	
	String dataScrollerId;
	
	String dataScrollerTableId;
	
	String dataTableId;
	
	static final String [] activePageClasses = new String[] {
		"dr-dscr-act","rich-datascr-act"
	};
	
	static final String [] inactivePageClasses = new String[] {
			"dr-dscr-inact","rich-datascr-inact"
	};
		
	static final String [] activeForwardClasses = new String[] {
			"dr-dscr-button","rich-datascr-button"
	};

	static final String [] inactiveForwardClasses = new String [] {
		"dr-dscr-button-dsbld",
		"rich-datascr-button-dsbld",
		"dr-dscr-button",
		"rich-datascr-button"
	};
	
	@SuppressWarnings("serial")
	static final List<String> events = new ArrayList<String>(){
		@Override
		public void clear() {
			
		}
	};
	static {
		events.add("onpagechange");
	}
	
	@Test
	public void testPagesVariables(Template template) {
		renderPage(template, RESET_METHOD_ME);
		initIDs(getParentId(), template);
		String commandId = getParentId() + "_controls:pageVars";
		clickCommandAndWait(commandId);
		
		String activePageId = getParentId() + "_data:activePage"; 
		String pageCountId = getParentId() + "_data:pagesCount";
		
		AssertTextEquals(activePageId, "Active page: 1", "PageIndexVar does not work.");
		AssertTextEquals(pageCountId, "Count of pages: 10", "PagesVar does not work.");
		
		clickControl(4);
		
		AssertTextEquals(activePageId, "Active page: 2", "PageIndexVar does not work.");
		AssertTextEquals(pageCountId, "Count of pages: 10", "PagesVar does not work.");

	}
	
	
	@Test
	public void testCancelableOnpagechnage(Template template) {
		renderPage(template, RESET_METHOD_ME);
		initIDs(getParentId(), template);
		String commandId = getParentId() + "_controls:onpagechange";
		clickCommandAndWait(commandId);
		
		assertClassNames(getPageLinkRefScript(4), inactivePageClasses, "'2' Link should be inactive", false);
		clickControlNotWait(4);
		assertClassNames(getPageLinkRefScript(4), inactivePageClasses, "Cancelable onpagechnage does not work. Page should not be switched. .'2' Link should be inactive", false);

	}
	
	
	@Test
	public void testAutoAjaxAttributes(Template template) {
		AutoTester autoTester = getAutoTester(this);
		
		dataScrollerTableId = autoTester.getClientId(AutoTester.COMPONENT_ID + "_table", template);
		
		autoTester.renderPage(template, RESET_METHOD_ME);
		autoTester.testAllAjaxAttributes();

	}
	
	@Override
	public void sendAjax() {
		clickControl(4);
		
	}
	
	@Override
	public String[] getReRendersId() {
		return new String [] {AutoTester.COMPONENT_ID, 
				(getTemplate().equals(Template.DATA_TABLE)) ? "tbl:0" : "tbl"};
	}
	
	@Override
	public String getAutoTestUrl() {
		return "pages/dataScroller/dataScrollerAjax.xhtml";
	}
	
	
	
		
	@Test
	public void testDataScrollerRendering(Template template) {
		renderPage(template, RESET_METHOD_ME);
		initIDs(getParentId(), template);
		
		testRendering();
		testHTMLEvent(dataScrollerId);
	}
	
	@Test
	public void testDataScrollerPagination(Template template) {
		renderPage(template, RESET_METHOD_ME);
		initIDs(getParentId(), template);
		
		testPageCount(16);
		
		clickControl(5);
		testData(1, "Page 3");
		
		assertClassNames(getPageLinkRefScript(5), activePageClasses, "'3' link should current", false);
		assertClassNames(getPageLinkRefScript(3), inactivePageClasses, "'1' link should be inactive", false);
		assertClassNames(getPageLinkRefScript(0), activeForwardClasses, "'««' control should be accessible", false);
		assertClassNames(getPageLinkRefScript(1), activeForwardClasses, "'«' control should be accessible", false);
		
		clickControl(10);
		testData(1, "Page 8");
		assertClassNames(getPageLinkRefScript(10), activePageClasses, "'8' link should current", false);
		
		clickControl(15);
		testData(1, "Page 10");
		assertClassNames(getPageLinkRefScript(15), inactiveForwardClasses, "'»»' control should be inactive", false);
		assertClassNames(getPageLinkRefScript(14), inactiveForwardClasses, "'»' control should be inactive", false);
		
		clickControl(1);
		testData(1, "Page 9");
		assertClassNames(getPageLinkRefScript(0), activeForwardClasses, "'»»' control should be active", false);
		assertClassNames(getPageLinkRefScript(1), activeForwardClasses, "'»' control should be active", false);
		assertClassNames(getPageLinkRefScript(11), activePageClasses, "'9' link should be current", false);
		
		clickControl(0);
		testData(1, "Page 1");
		assertClassNames(getPageLinkRefScript(3), activePageClasses, "'1' link should be current", false);
		assertClassNames(getPageLinkRefScript(4), inactivePageClasses, "'2' link should be inactive", false);

		clickControl(14);
		testData(1, "Page 2");
		assertClassNames(getPageLinkRefScript(3), inactivePageClasses, "'1' link should be inactive", false);
		assertClassNames(getPageLinkRefScript(4), activePageClasses, "'2' link should be current", false);
	
				
	}
	
	@Test
	public void testMaxPagesAttr(Template template) {
		renderPage(template, RESET_METHOD_ME);
		initIDs(getParentId(), template);
		
		testPageCount(16);
		
		String buttonId = getParentId() + "_controls:maxP";
		clickCommandAndWait(buttonId);
		
		testPageCount(11);
		
		String text = selenium.getTable("id=" + dataScrollerTableId + ".0.5");
		Assert.assertEquals(text, "3", "'3' link should be in the middle");
		
		clickControl(7);
		testPageCount(11);
		text = selenium.getTable("id=" + dataScrollerTableId + ".0.5");
		Assert.assertEquals(text, "5", "'5' link should be in the middle");
		testData(1, "Page 5");
		
		
		clickControl(10);
		testPageCount(11);
		text = selenium.getTable("id=" + dataScrollerTableId + ".0.7");
		Assert.assertEquals(text, "10");
		text = selenium.getTable("id=" + dataScrollerTableId + ".0.3");
		Assert.assertEquals(text, "6");
		testData(1, "Page 10");
		
		clickControl(3);
		testPageCount(11);
		text = selenium.getTable("id=" + dataScrollerTableId + ".0.5");
		Assert.assertEquals(text, "6");
		text = selenium.getTable("id=" + dataScrollerTableId + ".0.3");
		Assert.assertEquals(text, "4");
		testData(1, "Page 6");
		
		clickControl(1);
		clickControl(1);
		testPageCount(11);
		text = selenium.getTable("id=" + dataScrollerTableId + ".0.5");
		Assert.assertEquals(text, "4");
		text = selenium.getTable("id=" + dataScrollerTableId + ".0.3");
		Assert.assertEquals(text, "2");
		testData(1, "Page 4");
				
	
	}
	
	
	@Test
	public void testChangedData(Template template) {
		renderPage(template, RESET_METHOD_ME);
		initIDs(getParentId(), template);
		
		String tableRowsId = getParentId() + "_controls:tableRow";
		setValueById(tableRowsId, "2");
		
		String applyId = getParentId() + "_controls:apply";
		clickCommandAndWait(applyId);
		
		testPageCount(11);
		assertRowsCount(2, dataTableId);
		
		clickControl(7);
		String text = selenium.getTable("id=" + dataScrollerTableId + ".0.7");
		Assert.assertEquals(text, "5", "5th page should be displayed");
		assertRowsCount(2, dataTableId);
		
		clickControl(3);
		text = selenium.getTable("id=" + dataScrollerTableId + ".0.3");
		Assert.assertEquals(text, "1", "1st page should be displayed");
		assertRowsCount(2, dataTableId);
		
		
	}
	

	private void initIDs(String parentId, Template template) {
		dataScrollerId = parentId + "_data:scroller";
		dataScrollerTableId = parentId + "_data:scroller_table";
		
		//FIXME: currently dataTableId is invalid (dataTableId + ':0'). May be it's cause of problem with component state storing inside dataTable.
		dataTableId = (!template.getName().equals(Template.DATA_TABLE.getName())) ? parentId + "_data:tbl" : parentId + "_data:tbl:0";
	}
	
	private void testHTMLEvent(String id) {
		List<String> event = new ArrayList<String>();
		event.add("onclick");
		event.add("onmousedown");
		event.add("onmousemove");
		event.add("onmouseout");
		event.add("onmouseover");
		event.add("onmouseup");
		
		clickById(id);	
		selenium.mouseDown(id);
		selenium.mouseMove(id);
		selenium.mouseOut(id);
		selenium.mouseOver(id);
		selenium.mouseUp(id);
		
		assertEvents(event);
		
		
	}
	
	private void testRendering() {
		assertClassNames(dataScrollerId,new String [] 
		                                            {"dr-dscr",
		                                             "rich-datascr"},
		                 "DataScroller rendering failed: ", true);
		
		assertClassNames(dataScrollerTableId,new String [] 
		                                            {"dr-dscr-t",
		                                             "rich-dtascroller-table"},
		                 "DataScroller rendering failed: ", true);

		testPageCount(16);
		testControls();
		testData(1,"Page 1");
		checkCustomFacets();
	}
	

	private void testPageCount(int n) {
		assertColumnsCount(n, dataScrollerTableId, "DataScroller inner table contains invalid columns count");
	}
	
	private void testControls() {
		// Check '««' link 
		String text = selenium.getTable("id=" + dataScrollerTableId + ".0.0");
		Assert.assertEquals("««", text, "DataScroller does not contain '««' link or its position is invalid");
		assertClassNames(getPageLinkRefScript(0),inactiveForwardClasses,
		                 "DataScroller rendering failed: ", false);
		
		// Check '«' link
		text = selenium.getTable("id=" + dataScrollerTableId + ".0.1");
		Assert.assertEquals("«", text, "DataScroller does not contain '«' link or its position is invalid");
		assertClassNames(getPageLinkRefScript(1),inactiveForwardClasses,
		                 "DataScroller rendering failed: ", false);
		
		// Check '1' link
		text = selenium.getTable("id=" + dataScrollerTableId + ".0.3");
		Assert.assertEquals("1", text, "DataScroller does not contain '1' link or its position is invalid");
		assertClassNames(getPageLinkRefScript(3),activePageClasses,
		 		                 "DataScroller rendering failed: ", false);
		
		// Check '5' link
		text = selenium.getTable("id=" + dataScrollerTableId + ".0.7");
		Assert.assertEquals("5", text, "DataScroller does not contain '5' link or its position is invalid");
		assertClassNames(getPageLinkRefScript(7),inactivePageClasses,
		 		                 "DataScroller rendering failed: ", false);
		
		// Check '»' link
		text = selenium.getTable("id=" + dataScrollerTableId + ".0.14");
		Assert.assertEquals("»", text, "DataScroller does not contain '»' link or its position is invalid");
		assertClassNames(getPageLinkRefScript(14),activeForwardClasses,
		 		                 "DataScroller rendering failed: ", false);
		
		// Check '»»' link
		text = selenium.getTable("id=" + dataScrollerTableId + ".0.15");
		Assert.assertEquals("»»", text, "DataScroller does not contain '»»' link or its position is invalid");
		assertClassNames(getPageLinkRefScript(15),activeForwardClasses,
		 		                 "DataScroller rendering failed: ", false);

	}
	
	private void checkCustomFacets() {
		String text = selenium.getTable("id=" + dataScrollerTableId + ".0.2");
		Assert.assertEquals("", text, "'Previous' facet should be rendered yet");
		assertClassNames(getPageLinkRefScript(2),inactiveForwardClasses,
		 		                 "DataScroller rendering failed: ", false);
		
		text = selenium.getTable("id=" + dataScrollerTableId + ".0.13");
		Assert.assertEquals("Next", text, "'Next' facet didnot rendered. DataScroller does not contain 'Next' link or its position is invalid");
		assertClassNames(getPageLinkRefScript(13),activeForwardClasses,
		 		                 "DataScroller rendering failed: ", false);
		clickControl(4);
		
		text = selenium.getTable("id=" + dataScrollerTableId + ".0.2");
		Assert.assertEquals("Previous", text, "'Previous' facet didnot be rendered.");
		assertClassNames(getPageLinkRefScript(2),activeForwardClasses,
		 		                 "DataScroller rendering failed: ", false);
			
		
	}
	
	private void testData(int rowCount, String data) {
		assertRowsCount(rowCount, dataTableId);
		
		for (int i=1; i <= rowCount; i++) {
			String text = selenium.getTable("id=" + dataTableId + "."+rowCount+".1");
			Assert.assertEquals(data, text,"Data Table content is invalid");
		}
	}
	
	private String getPageLinkRefScript(int n) {
		StringBuffer b = new StringBuffer(WINDOW_JS_RESOLVER);
		b.append("$('");
		b.append(dataScrollerTableId);
		b.append("').rows[0].cells[");
		b.append(n);
		b.append("]");
		return b.toString();
	}
	
	private void clickControl(int n) {
		StringBuffer b = new StringBuffer();
		b.append(getPageLinkRefScript(n));
		b.append(".onclick();");
		selenium.getEval(b.toString());		
		waitForAjaxCompletion();
		assertEvents(events);
	}
	
	private void clickControlNotWait(int n) {
		StringBuffer b = new StringBuffer();
		b.append(getPageLinkRefScript(n));
		b.append(".onclick();");
		selenium.getEval(b.toString());		
	}
	
	/* (non-Javadoc)
	 * @see org.richfaces.SeleniumTestBase#getTestUrl()
	 */
	@Override
	public String getTestUrl() {
		return TEST__URL;
	}

}

