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.element = getCurrentScript().parentNode; 
    this.tableElement = this.element.getElementsByTagName("table")[0];
    this.menu = this.element.getElementsByTagName("ol")[1];
    this.element.table = this;

    this.getTableElement = function () {
        return this.tableElement;
    }

    this.updateTable = function (command) {
        var table = this.getTableElement();
        addNodeClass(this.element, "updating");

        var xmlRequest = newXMLRequest();
        var commands = "<commands>" + command + "</commands>";

        xmlRequest.open("POST", this.URI, true);
	    xmlRequest.setRequestHeader("Content-Type", "application/xml");
        xmlRequest.onreadystatechange = this.createHTTPResponseHandler(xmlRequest);
        xmlRequest.send(commands);
    }

    this.columnClicked = function (columnIdentifier) {
        this.updateTable("<sortColumn id=\"" + columnIdentifier + "\"/>");
    }

    this.createFilterTextTimeoutHandler = function (textBox, columnIdentifier) {
        var component = this;

        return function () { component.updateTable("<filterColumn id=\"" + columnIdentifier + "\" 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("<editing enabled=\"" + 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, columnIdentifier) {
        this.filterTimer.kill();
        this.filterTimer.schedule(this.createFilterTextTimeoutHandler(textBox, columnIdentifier));
    }

    this.moveCursor = function (direction) {
        this.updateTable("<cursorMove direction=\"" + direction + "\"/>");
    }

    this.switchCursorStatus = function () {
        this.updateTable("<cursorStatus/>");
    }

    this.createHTTPResponseHandler = function (http) {
        var field = this;

        return function () {
            field.handleHTTPResponse(http);
        };
    }

    this.handleHTTPResponse = function (http) {
        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;
                
                this.element.replaceChild(newTable, this.tableElement);
                this.tableElement = newTable;

                if (this.rowSelectorEnabled)
                    this.attachRowSelectorEventHandlers(this.tableElement);

                this.fireChangedEvent(this.tableElement);
            }

            removeNodeClass(this.element, "updating");
            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.hideMenu = function () {
        collapse(this.menu);
    }
}

