package org.richfaces.testng;

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

public class DataTableTest extends SeleniumTestBase {

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

    @Test
    public void testDataTable(Template template) {
        renderPage(template);

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

        writeStatus("Check columns count equals to 3 ");
        assertColumnsCount(3, dataTableId);
        writeStatus("Check rows count equals to 20 ");
        assertRowsCount(20, 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(getParentId() + "_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(getParentId(), 10, 5, 0, 100);

        writeStatus("Check columns count equals to 5 ");
        assertColumnsCount(5, dataTableId);
        writeStatus("Check rows count equals to 10 ");
        assertRowsCount(10, 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(getParentId(),2, 5, 2, 2);
        assertColumnsCount(1, dataTableId);
        assertRowsCount(2, dataTableId);

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

    }
    
    public void reset(String id) {
    	clickAjaxCommandAndWait(id);
    }

    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(String parentId, int rows, int columns, int begin, int end) {
        String script = "$('"+parentId+"_controls:rows').value='" + String.valueOf(rows) + "';";
        runScript(script);
        script = "$('"+parentId+"_controls:column').value='" + String.valueOf(columns) + "';";
        runScript(script);
        script = "$('"+parentId+"_controls:begin').value='" + String.valueOf(begin) + "';";
        runScript(script);
        script = "$('"+parentId+"_controls:end').value='" + String.valueOf(end) + "';";
        runScript(script);
        clickById(parentId +"_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);
    }

}
