function Table(URI) {
    this.onChanged = null;
    this.onEditingChanged = null;
    this.editingEnabled = false;
    this.filterTimer = new Timer(600);
    this.filterEnabled = false;
    this.rowSelectorEnabled = false;
    this.URI = URI;
    this.tableElement = getParentNode(getCurrentScript(), "table");
    this.tableElement.table = this;

    this.getTableElement = function () {
        return this.tableElement;
    }

    this.updateTable = function (table, URL) {
//        var table = this.getTableElement();
        addNodeClass(table, "updating");

        var request = newXMLRequest();

        request.open("get", URL, true);
        request.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
        request.onreadystatechange = this.createHTTPResponseHandler(request, table);
        request.send(null);
    }

    this.columnClicked = function (column, URL) {
        this.updateTable(getParentNode(column, "table"), URL);
    }

    this.createFilterTextTimeoutHandler = function (textBox, URL) {
        var table = getParentNode(textBox, "table");
        var component = this;

        return function () { component.updateTable(table, URL + '&text=' + encodeURIComponent(textBox.value)); };
    }

    this.getHeaderRowWithClass = function (className) {
        var table = this.getTableElement();
        var rows = table.tHead.rows;
        var result = null;
        var i = 0;

        while (result == null && i < rows.length) {
            if (nodeHasClass(rows[i], className))
                result = rows[i];
            else
                i++;
        }

        return result;
    }

    this.getFilterRow = function () {
        return this.getHeaderRowWithClass("filter");
    }

    this.toggleFilter = function () {
        this.filterEnabled = !this.filterEnabled;
        this.updateFilterVisibility();
    }

    this.setFilterEnabled = function (enabled) {
        this.filterEnabled = enabled;
        this.updateFilterVisibility();
    }

    this.updateFilterVisibility = function () {
        setNodeClassEnabled(this.getFilterRow(), "disabled", !this.filterEnabled);
    }

    this.toggleEdit = function () {
        this.editingEnabled = !this.editingEnabled;
        this.updateEditing();
        this.updateTable(this.getTableElement(), this.URI + '?setEditingEnabled=' + this.editingEnabled);
        this.fireOnEditingChangedEvent();
    }

    this.updateEditing = function () {
        var table = this.getTableElement();
        setNodeClassEnabled(table, "edit", this.editingEnabled);
        setNodeClassEnabled(table, "view", !this.editingEnabled);
    }

    this.setEditingEnabled = function (enabled) {
        this.editingEnabled = enabled;
        this.updateEditing();
    }

    this.columnFilterTextChanged = function (textBox, URL) {
        this.filterTimer.kill();
        this.filterTimer.schedule(this.createFilterTextTimeoutHandler(textBox, URL));
    }

    this.createHTTPResponseHandler = function (http, table) {
        var field = this;

        return function () {
            field.handleHTTPResponse(http, table);
        };
    }

    this.handleHTTPResponse = function (http, table) {
        if (http.readyState == 4) {
            var newTableDivision = document.createElement("div");
            newTableDivision.innerHTML = http.responseText;

            if (http.responseText.substr(0, 6).toLowerCase() == "<table") {
                var newTable = newTableDivision.firstChild;
                table.parentNode.replaceChild(newTable, table);
                this.tableElement = newTable;
                this.tableElement.table = this;
                this.fireChangedEvent(newTable);
            }

            removeNodeClass(table, "updating");

            if (this.rowSelectorEnabled)
                this.attachRowSelectorEventHandlers(newTable);

            this.updateFilterVisibility();
        }
    }

    this.fireChangedEvent = function (newTable) {
        if (this.onChanged !== null)
            this.onChanged(newTable);
    }

    this.fireOnEditingChangedEvent = function () {
        if (this.onEditingChanged !== null)
            this.onEditingChanged(this);
    }

    this.selectRow = function (checkBox) {
        var tableRow = getParentNode(checkBox, "tr");
        setNodeClassEnabled(tableRow, "selectedRow", checkBox.checked);
    }

    this.selectAllRows = function (checkBox) {
        var table = this.getTableElement();

        for (var i = 0; i < table.tBodies.length; i++) {
            var rows = table.tBodies[i].rows;

            for (var j = 0; j < rows.length; j++) {
                var cell = rows[j].cells[0];
                var checkBoxToChange = cell.getElementsByTagName("input")[0];

                if (checkBoxToChange != null) 
                    checkBoxToChange.click();
            }
        }
    }

    this.createRowSelectionEventHandler = function (checkBox) {
        var table = this;

        return function () {
            table.selectRow(checkBox);
        };
    }

    this.attachRowSelectorEventHandlers = function (table) {
        for (var i = 0; i < table.tBodies.length; i++) {
            var rows = table.tBodies[i].rows;

            for (var j = 0; j < rows.length; j++) {
                var cell = rows[j].cells[0];
                var checkBox = cell.getElementsByTagName("input")[0];

                if (checkBox != null)
                    checkBox.onclick = this.createRowSelectionEventHandler(checkBox);
            }
        }
    }

    this.enableRowSelector = function () {
        this.rowSelectorEnabled = true;
        this.attachRowSelectorEventHandlers(this.getTableElement());
    }

    this.refresh = function () {
        this.updateTable(this.getTableElement(), this.URI);
    }
}

