package autotest.common.table;

import autotest.common.SimpleCallback;
import autotest.common.table.DataSource.DataCallback;
import autotest.common.table.DataSource.Query;
import autotest.common.table.DataSource.SortDirection;
import autotest.common.table.DataSource.SortSpec;
import autotest.common.ui.Paginator;

import com.google.gwt.json.client.JSONObject;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Image;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

/**
 * Extended DataTable supporting sorting, filtering and pagination.
 */
public class DynamicTable extends DataTable implements DataCallback {
    public static final int NO_COLUMN = -1;
    public static final String SORT_UP_IMAGE = "arrow_up.png",
                               SORT_DOWN_IMAGE = "arrow_down.png";

    public static interface DynamicTableListener extends DataTableListener {
        public void onTableRefreshed();
    }

    static class SortIndicator extends Composite {
        public int column;
        private Image image = new Image();

        public SortIndicator(int column) {
            this.column = column;
            initWidget(image);
            setVisible(false);
        }

        public void sortOn(SortDirection direction) {
            image.setUrl(direction == SortDirection.ASCENDING ? SORT_UP_IMAGE : SORT_DOWN_IMAGE);
            setVisible(true);
        }

        public void sortOff() {
            setVisible(false);
        }
    }

    protected DataSource dataSource;
    private Query currentQuery;

    private boolean clientSortable = false;
    private SortIndicator[] sortIndicators;
    private List<SortSpec> sortColumns = new ArrayList<SortSpec>();

    protected List<Filter> filters = new ArrayList<Filter>();
    protected List<Paginator> paginators = new ArrayList<Paginator>();
    protected Integer rowsPerPage;

    protected List<DynamicTableListener> dynamicTableListeners =
        new ArrayList<DynamicTableListener>();

    public DynamicTable(String[][] columns, DataSource dataSource) {
        super(columns);
        setDataSource(dataSource);
    }

    // SORTING

    /**
     * Makes the table client sortable, that is, sortable by the user by
     * clicking on column headers.
     */
    public void makeClientSortable() {
        this.clientSortable = true;
        table.getRowFormatter().addStyleName(0,
                                         DataTable.HEADER_STYLE + "-sortable");

        sortIndicators = new SortIndicator[columns.length];
        for(int i = 0; i < columns.length; i++) {
            sortIndicators[i] = new SortIndicator(i);

            // we have to use an HTMLPanel here to preserve styles correctly and
            // not break hover
            // we add a <span> with a unique ID to hold the sort indicator
            String name = columns[i][COL_TITLE];
            String id = HTMLPanel.createUniqueId();
            HTMLPanel panel = new HTMLPanel(name +
                                            " <span id=\"" + id + "\"></span>");
            panel.add(sortIndicators[i], id);
            table.setWidget(0, i, panel);
        }
    }

    private void updateSortIndicators() {
        if (!clientSortable) {
            return;
        }

        SortSpec firstSpec = getFirstSortSpec();
        for (SortIndicator indicator : sortIndicators) {
            if (columns[indicator.column][COL_NAME].equals(firstSpec.getField())) {
                indicator.sortOn(firstSpec.getDirection());
            } else {
                indicator.sortOff();
            }
        }
    }

    private SortSpec getFirstSortSpec() {
        if (sortColumns.isEmpty()) {
            return null;
        }
        return sortColumns.get(0);
    }

    /**
     * Set column on which data is sorted.  You must call <code>refresh()</code>
     * after this to display the results.
     * @param columnField field of the column to sort on
     * @param sortDirection DynamicTable.ASCENDING or DynamicTable.DESCENDING
     */
    public void sortOnColumn(String columnField, SortDirection sortDirection) {
        // remove any existing sort on this column
        for (Iterator<SortSpec> i = sortColumns.iterator(); i.hasNext(); ) {
            if (i.next().getField().equals(columnField)) {
                i.remove();
                break;
            }
        }

        sortColumns.add(0, new SortSpec(columnField, sortDirection));
        updateSortIndicators();
    }

    /**
     * Defaults to ascending order.
     */
    public void sortOnColumn(String columnField) {
        sortOnColumn(columnField, SortDirection.ASCENDING);
    }

    public void clearSorts() {
        sortColumns.clear();
        updateSortIndicators();
    }

    // PAGINATION

    /**
     * Attach a new paginator to this table.
     */
    public void attachPaginator(Paginator paginator) {
        assert rowsPerPage != null;
        paginators.add(paginator);
        paginator.addCallback(new SimpleCallback() {
            public void doCallback(Object source) {
                setPaginatorStart(((Paginator) source).getStart());
                fetchPage();
            }
        });
        paginator.setResultsPerPage(rowsPerPage.intValue());
    }

    /**
     * Set the page size of this table (only useful if you attach paginators).
     */
    public void setRowsPerPage(int rowsPerPage) {
        assert rowsPerPage > 0;
        this.rowsPerPage = Integer.valueOf(rowsPerPage);
        for (Paginator paginator : paginators) {
            paginator.setResultsPerPage(rowsPerPage);
        }
    }

    /**
     * Set start row for pagination.  You must call
     * <code>refresh()</code> after this to display the results.
     */
    public void setPaginatorStart(int start) {
        for (Paginator paginator : paginators) {
            paginator.setStart(start);
        }
    }

    protected void refreshPaginators() {
        for (Paginator paginator : paginators) {
            paginator.update();
        }
    }

    protected void updatePaginatorTotalResults(int totalResults) {
        for (Paginator paginator : paginators) {
            paginator.setNumTotalResults(totalResults);
        }
    }


    // FILTERING

    public void addFilter(Filter filter) {
        filters.add(filter);
        filter.addCallback(new SimpleCallback() {
            public void doCallback(Object source) {
                setPaginatorStart(0);
                refresh();
            }
        });
    }

    protected void addFilterParams(JSONObject params) {
        for (Filter filter : filters) {
            if (filter.isActive()) {
                filter.addParams(params);
            }
        }
    }

    public boolean isAnyUserFilterActive() {
        for (Filter filter : filters) {
            if (filter.isUserControlled() && filter.isActive()) {
                return true;
            }
        }

        return false;
    }


    // DATA MANAGEMENT

    public void refresh() {
        JSONObject params = new JSONObject();
        addFilterParams(params);
        dataSource.query(params, this);
    }

    @Override
    public void onQueryReady(Query query) {
        currentQuery = query;
        if (!paginators.isEmpty()) {
            query.getTotalResultCount(this);
        }
        fetchPage();
    }

    private void fetchPage() {
        Integer start = null, limit = null;
        SortSpec[] sortOn = null;
        if (!paginators.isEmpty()) {
            Paginator p = paginators.get(0);
            start = Integer.valueOf(p.getStart());
            limit = Integer.valueOf(p.getResultsPerPage());
        }

        if (!sortColumns.isEmpty()) {
            sortOn = new SortSpec[sortColumns.size()];
            sortColumns.toArray(sortOn);
        }
        currentQuery.getPage(start, limit, sortOn, this);
    }

    @Override
    public void handleTotalResultCount(int totalCount) {
        updatePaginatorTotalResults(totalCount);
        refreshPaginators();
        notifyListenersRefreshed();
    }

    public void handlePage(List<JSONObject> data) {
        clear();
        addRows(data);
        refreshPaginators();
        notifyListenersRefreshed();
    }

    public String[] getRowData(int row) {
        String[] data = new String[columns.length];
        for (int i = 0; i < columns.length; i++) {
            if(isWidgetColumn(i)) {
                continue;
            }
            data[i] = table.getHTML(row, i);
        }
        return data;
    }

    public DataSource getDataSource() {
        return dataSource;
    }

    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public Query getCurrentQuery() {
        return currentQuery;
    }


    // INPUT

    @Override
    protected void onCellClicked(int row, int cell, boolean isRightClick) {
        if (row == headerRow) {
            if (isWidgetColumn(cell)) {
                // ignore sorting on widget columns
                return;
            }
            String columnName = columns[cell][COL_NAME];
            SortDirection newSortDirection = SortDirection.ASCENDING;
            SortSpec firstSortSpec = getFirstSortSpec();
            // when clicking on the last sorted field, invert the sort
            if (firstSortSpec != null && columnName.equals(firstSortSpec.getField())) {
                newSortDirection = invertSortDirection(firstSortSpec.getDirection());
            }

            sortOnColumn(columnName, newSortDirection);
            refresh();
            return;
        }

        super.onCellClicked(row, cell, isRightClick);
    }

    private SortDirection invertSortDirection(SortDirection direction) {
        return direction == SortDirection.ASCENDING ?
                                        SortDirection.DESCENDING : SortDirection.ASCENDING;
    }

    public void addListener(DynamicTableListener listener) {
        super.addListener(listener);
        dynamicTableListeners.add(listener);
    }

    public void removeListener(DynamicTableListener listener) {
        super.removeListener(listener);
        dynamicTableListeners.remove(listener);
    }

    protected void notifyListenersRefreshed() {
        for (DynamicTableListener listener : dynamicTableListeners) {
            listener.onTableRefreshed();
        }
    }

    public List<SortSpec> getSortSpecs() {
        return Collections.unmodifiableList(sortColumns);
    }

    public void onError(JSONObject errorObject) {
        // nothing to do
    }
}
