package org.richfaces.testng;

import org.ajax4jsf.template.Template;
import org.richfaces.RichSeleniumTest;
import org.richfaces.SeleniumTestBase;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

public class DataTableTest extends SeleniumTestBase implements RichSeleniumTest {

    public DataTableTest() {
        super("http", "localhost", serverPort);
    }

    /**
     * This method are invoking before selenium tests started
     */
    @BeforeMethod
    @Parameters({"browser", "filterPrefix"})
    public void startSelenium(String browser, String filterPrefix) {
    	super.startSelenium(browser, filterPrefix);
    }
    
    
    @BeforeMethod
    @Parameters({"loadStyleStrategy", "loadScriptStrategy"})
    protected void loadConfiguration(String loadStyleStrategy, String loadScriptStrategy) throws Exception {
	super.loadConfiguration(loadStyleStrategy, loadScriptStrategy);
    }

    /**
     * This method are invoking after selenium tests completed
     */
    @AfterMethod(alwaysRun=true)
    public void stopSelenium() {
        super.stopSelenium();
    }

    public String getTestUrl() {
        return "pages/dataTable/dataTableTest.xhtml";
    }

    @Test
    public void testDataTable() {
        _testDataTable(Template.SIMPLE);
    }

    private void _testDataTable(Template template) {
        renderPage(template);

        String parentId = getParentId() + "_form:";
        String dataTableId = parentId + "table";

        writeStatus("Check columns count equals to 3 ");
        assertColumnsCount(3, dataTableId);
        writeStatus("Check rows count equals to 22 ");
        assertRowsCount(22, dataTableId);

        String columnsId = getColumnId(dataTableId, 0);

        writeStatus("Check inputs' values ");
        assertInputValue(dataTableId, 0, columnsId, "0");
        assertInputValue(dataTableId, 5, columnsId, "5");
        assertInputValue(dataTableId, 19, columnsId, "19");

        columnsId = getColumnId(dataTableId, 1);

        assertInputValue(dataTableId, 0, columnsId, "1");
        assertInputValue(dataTableId, 7, columnsId, "8");
        assertInputValue(dataTableId, 19, columnsId, "20");

        columnsId = getColumnId(dataTableId, 2);

        assertInputValue(dataTableId, 0, columnsId, "2");
        assertInputValue(dataTableId, 11, columnsId, "13");
        assertInputValue(dataTableId, 19, columnsId, "21");

        writeStatus("Insert some values ");
        insertInputValue(dataTableId, 0, getColumnId(dataTableId, 0), "000");
        insertInputValue(dataTableId, 19, getColumnId(dataTableId, 2), "777");

        writeStatus("Rerender table");
        clickById("_form:submit");
        waitForAjaxCompletion();

        writeStatus("Check values entered ");
        assertInputValue(dataTableId, 0, getColumnId(dataTableId, 0), "000");
        assertInputValue(dataTableId, 19, getColumnId(dataTableId, 2), "777");

        columnsId = getColumnId(dataTableId, 0);

        writeStatus("Sort ASC by 1'st column ");
        sortColumn(dataTableId, columnsId);
        writeStatus("Check ordering");
        assertInputValue(dataTableId, 0, columnsId, "000");
        assertInputValue(dataTableId, 1, columnsId, "1");
        assertInputValue(dataTableId, 18, columnsId, "8");
        assertInputValue(dataTableId, 19, columnsId, "9");

        writeStatus("Sort DESC by 1'st column ");
        sortColumn(dataTableId, columnsId);
        writeStatus("Check ordering");
        assertInputValue(dataTableId, 0, columnsId, "9");
        assertInputValue(dataTableId, 1, columnsId, "8");
        assertInputValue(dataTableId, 18, columnsId, "1");
        assertInputValue(dataTableId, 19, columnsId, "000");

        columnsId = getColumnId(dataTableId, 2);

        writeStatus("Sort ASC by 3'st column ");
        sortColumn(dataTableId, columnsId);
        writeStatus("Check ordering");
        assertInputValue(dataTableId, 0, columnsId, "10");
        assertInputValue(dataTableId, 1, columnsId, "11");
        assertInputValue(dataTableId, 18, columnsId, "8");
        assertInputValue(dataTableId, 19, columnsId, "9");

        writeStatus("Set columns count == 5, rows count == 10");
        changeColumnCount(10, 5, 0, 100);

        writeStatus("Check columns count equals to 5 ");
        assertColumnsCount(5, dataTableId);
        writeStatus("Check rows count equals to 12 ");
        assertRowsCount(12, dataTableId);

        columnsId = getColumnId(dataTableId, 0);

        writeStatus("Check inputs' values ");
        assertInputValue(dataTableId, 0, columnsId, "0");
        assertInputValue(dataTableId, 5, columnsId, "5");
        assertInputValue(dataTableId, 9, columnsId, "9");

        columnsId = getColumnId(dataTableId, 1);

        assertInputValue(dataTableId, 0, columnsId, "1");
        assertInputValue(dataTableId, 7, columnsId, "8");
        assertInputValue(dataTableId, 9, columnsId, "10");

        columnsId = getColumnId(dataTableId, 4);

        assertInputValue(dataTableId, 0, columnsId, "4");
        assertInputValue(dataTableId, 2, columnsId, "6");
        assertInputValue(dataTableId, 9, columnsId, "13");

        writeStatus("Sort ASC by the last column ");
        sortColumn(dataTableId, columnsId);
        writeStatus("Check ordering");
        assertInputValue(dataTableId, 0, columnsId, "10");
        assertInputValue(dataTableId, 2, columnsId, "12");
        assertInputValue(dataTableId, 9, columnsId, "9");

        writeStatus("Sort DESC by the last column ");
        sortColumn(dataTableId, columnsId);
        writeStatus("Check ordering");
        assertInputValue(dataTableId, 0, columnsId, "9");
        assertInputValue(dataTableId, 2, columnsId, "7");
        assertInputValue(dataTableId, 9, columnsId, "10");

        columnsId = getColumnId(dataTableId, 2);
        writeStatus("Sort ASC by the 3d column ");
        sortColumn(dataTableId, columnsId);

        writeStatus("Check ordering");
        assertInputValue(dataTableId, 0, columnsId, "10");
        assertInputValue(dataTableId, 2, columnsId, "2");
        assertInputValue(dataTableId, 9, columnsId, "9");

        changeColumnCount(2, 5, 2, 2);
        assertColumnsCount(1, dataTableId);
        assertRowsCount(4, dataTableId);

        changeColumnCount(10, 5, 10, 0);
        assertRowsCount(0, dataTableId);

    }

    private String getColumnId(String tableId, int i) {
        String script = "$('" + tableId + "').rows[0].cells[" + String.valueOf(i) + "].id";
        String id = runScript(script);
        id = id.replace(tableId + ":", "");
        id = id.replace("header", "");
        return id;
    }

    private void changeColumnCount(int rows, int columns, int begin, int end) {
        String script = "$('_controls:rows').value='" + String.valueOf(rows) + "';";
        runScript(script);
        script = "$('_controls:column').value='" + String.valueOf(columns) + "';";
        runScript(script);
        script = "$('_controls:begin').value='" + String.valueOf(begin) + "';";
        runScript(script);
        script = "$('_controls:end').value='" + String.valueOf(end) + "';";
        runScript(script);
        clickById("_controls:apply");
        waitForAjaxCompletion();
    }

    private void sortColumn(String tableId, String columnId) {
        clickById(tableId + ":" + columnId + "header");
        waitForAjaxCompletion();
    }

    private void insertInputValue(String tableId, int row, String inputId, String value) {
        String id = tableId + ":" + row + ":" + inputId;
        String script = ("$('" + id + "').firstChild.value='" + value + "';");
        runScript(script);
    }

    private void assertInputValue(String tableId, int row, String inputId, String value) {
        String id = tableId + ":" + row + ":" + inputId;
        String script = "$('" + id + "').firstChild.value";
        Assert.assertEquals(runScript(script), value);
    }

    private void assertColumnsCount(int i, String tableId) {
        StringBuffer script = new StringBuffer("$('");
        script.append(tableId);
        script.append("').rows[0].cells.length");

        String count = runScript(script.toString());
        Assert.assertEquals(count, String.valueOf(i));
    }

    private void assertRowsCount(int i, String tableId) {
        StringBuffer script = new StringBuffer("$('");
        script.append(tableId);
        script.append("').rows.length");

        String count = runScript(script.toString());
        Assert.assertEquals(count, String.valueOf(i));
    }

}
