package autotest.tko;

import autotest.common.StatusSummary;
import autotest.common.spreadsheet.Spreadsheet;
import autotest.common.spreadsheet.Spreadsheet.CellInfo;
import autotest.common.spreadsheet.Spreadsheet.Header;
import autotest.common.spreadsheet.Spreadsheet.HeaderImpl;
import autotest.common.table.DataSource.DataCallback;
import autotest.common.table.DataSource.Query;
import autotest.common.ui.NotifyManager;

import com.google.gwt.core.client.Duration;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.IncrementalCommand;

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

public class SpreadsheetDataProcessor implements DataCallback {
    private static final NotifyManager notifyManager = NotifyManager.getInstance();
    private static final int MAX_CELL_COUNT = 500000;
    private static final int ROWS_PROCESSED_PER_ITERATION = 1000;

    private Spreadsheet spreadsheet;
    private TestGroupDataSource dataSource;
    private int numTotalTests;
    private CellInfo lastCellInfo;

    private Header rowFields, columnFields;
    private Command onFinished;
    private Duration timer;
    private Query currentQuery;

    public static class TooManyCellsError extends Exception {
        public int cellCount;

        public TooManyCellsError(int cellCount) {
            super();
            this.cellCount = cellCount;
        }
    }

    private class ProcessDataCommand implements IncrementalCommand {
        private int state = 0;
        private List<JSONObject> counts;
        private int currentRow = 0;

        public ProcessDataCommand(List<JSONObject> counts) {
            this.counts = counts;
        }

        public void processSomeRows() {
            for (int i = 0; i < ROWS_PROCESSED_PER_ITERATION; i++, currentRow++) {
                if (currentRow == counts.size()) {
                    state++;
                    return;
                }
                processRow(counts.get(currentRow).isObject());
            }
        }

        public boolean execute() {
            switch (state) {
                case 0:
                    notifyManager.setLoading(true);
                    numTotalTests = 0;
                    try {
                        processHeaders();
                    } catch (TooManyCellsError exc) {
                        notifyManager.showError("Resulting spreadsheet contains " + exc.cellCount +
                                                " cells, " + "exceeding maximum " + MAX_CELL_COUNT);
                        finalizeCommand();
                        return false;
                    }
                    break;
                case 1:
                    spreadsheet.prepareForData();
                    break;
                case 2:
                    processSomeRows();
                    return true;
                case 3:
                    // we must make the spreadsheet visible before rendering, or size computations
                    // won't work correctly
                    spreadsheet.setVisible(true);
                    break;
                case 4:
                    spreadsheet.render(this);
                    state++;
                    return false; // render will re-add us to the command queue
                case 5:
                    logTimer("Rendering");
                    finalizeCommand();
                    return false;
            }

            state++;
            return true;
        }

        private void finalizeCommand() {
            notifyManager.setLoading(false);
            onFinished.execute();
        }
    }

    public SpreadsheetDataProcessor(Spreadsheet spreadsheet) {
        this.spreadsheet = spreadsheet;
    }

    public void processHeaders() throws TooManyCellsError {
        spreadsheet.setHeaderFields(rowFields, columnFields);
        List<List<String>> rowHeaderValues = dataSource.getHeaderGroupValues(0);
        List<List<String>> columnHeaderValues = dataSource.getHeaderGroupValues(1);
        int totalCells = rowHeaderValues.size() * columnHeaderValues.size();
        if (totalCells > MAX_CELL_COUNT) {
            throw new TooManyCellsError(totalCells);
        }
        for (List<String> header : rowHeaderValues) {
            spreadsheet.addRowHeader(header);
        }
        for (List<String> header : columnHeaderValues) {
            spreadsheet.addColumnHeader(header);
        }
    }

    private void processRow(JSONObject group) {
        JSONArray headerIndices = group.get("header_indices").isArray();
        int row = (int) headerIndices.get(0).isNumber().doubleValue();
        int column = (int) headerIndices.get(1).isNumber().doubleValue();
        CellInfo cellInfo = spreadsheet.getCellInfo(row, column);
        StatusSummary statusSummary = StatusSummary.getStatusSummary(
            group,
            TestGroupDataSource.PASS_COUNT_FIELD,
            TestGroupDataSource.COMPLETE_COUNT_FIELD,
            TestGroupDataSource.INCOMPLETE_COUNT_FIELD,
            TestGroupDataSource.GROUP_COUNT_FIELD);
        numTotalTests += statusSummary.getTotal();
        cellInfo.contents = statusSummary.formatContents();
        cellInfo.cssClass = statusSummary.getCssClass();
        cellInfo.testCount = statusSummary.getTotal();
        cellInfo.testIndex = (int) group.get("test_idx").isNumber().doubleValue();
        lastCellInfo = cellInfo;
    }

    public void refresh(JSONObject condition, Command onFinished) {
        timer = new Duration();
        this.onFinished = onFinished;
        dataSource.query(condition, this);
    }

    public void onQueryReady(Query query) {
        currentQuery = query;
        query.getPage(null, null, null, this);
    }

    public void handlePage(List<JSONObject> data) {
        logTimer("Server response");
        if (data.size() == 0) {
            notifyManager.showMessage("No results for query");
            onFinished.execute();
            return;
        }

        DeferredCommand.addCommand(new ProcessDataCommand(data));
    }

    public void handleTotalResultCount(int totalCount) {}

    private void logTimer(String message) {
        notifyManager.log(message + ": " + timer.elapsedMillis() + " ms");
        timer = new Duration();
    }

    public int getNumTotalTests() {
        return numTotalTests;
    }

    /**
     * This is useful when there turns out to be only a single test return.
     * @return the last CellInfo created.  Should only really be called when there was only a single
     *         one.
     */
    public CellInfo getLastCellInfo() {
        assert numTotalTests == 1;
        return lastCellInfo;
    }

    public void onError(JSONObject errorObject) {
        onFinished.execute();
    }

    public void setHeaders(List<HeaderField> rowFields, List<HeaderField> columnFields,
                           JSONObject queryParameters) {
        this.rowFields = getHeaderSqlNames(rowFields);
        this.columnFields = getHeaderSqlNames(columnFields);

        List<List<String>> headerGroups = new ArrayList<List<String>>();
        headerGroups.add(this.rowFields);
        headerGroups.add(this.columnFields);
        dataSource.setHeaderGroups(headerGroups);
        dataSource.setQueryParameters(queryParameters);
    }

    private Header getHeaderSqlNames(List<HeaderField> fields) {
        Header header = new HeaderImpl();
        for (HeaderField field : fields) {
            header.add(field.getSqlName());
        }
        return header;
    }

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

    public TestGroupDataSource getDataSource() {
        return dataSource;
    }

    public Query getCurrentQuery() {
        return currentQuery;
    }
}
