var quickFS_GUI = function() {
    var DATA, CONVERT, CONTRACT_STATUS, ACTION, ROWPAGER;
    var $parent, $filter, $rowCount, $result, $rowPager;

    const ONE_DAY_IN_MILLIS = 86400000;

	const KPI_TYPE_HIGHEST_VALUE = "0";
	const KPI_TYPE_LOWEST_VALUE = "1";
	const KPI_TYPE_LOWEST_VALUE_WITH_DURATION = "2";
	const KPI_TYPE_HIGHEST_VALUE_WITH_DURATION = "3";
	const KPI_TYPE_VALUE_WITH_LONGEST_DURATION = "4";
	const KPI_TYPE_AVERAGE_VALUE = "5";
	const KPI_TYPE_WEIGHTED_AVERAGE = "6";
	const KPI_TYPE_COUNT_DATES = "7";
	const KPI_TYPE_COUNT_ROWS = "8";
	const KPI_TYPE_WEIGHTED_AVERAGE_MULTIPLE_TABLES = "9";
	const KPI_TYPE_EITHER_OR = "10";
	const KPI_TYPE_PERCENTAGE = "11";

    return {
        "clearResult":clearResult,

        "viewPage":viewPage,

        "getSelectedRows":getSelectedRows,

        "writeSubRows":writeSubRows,
        "hasSubRows":hasSubRows,
        "hideSubRows":hideSubRows,
        "showSubRows":showSubRows,

        "showFilterForm":showFilterForm,
        "getFilter":getFilter,

        "bindRowPager":bindRowPager,

        "setResultStatus":setResultStatus,
        "clearResultStatus":clearResultStatus,

        "setWaitStatus":setWaitStatus,
        "clearWaitStatus":clearWaitStatus,

        "getValue":getValue,
        "setValue":setValue,

        "init":init
    };

    function clearResultStatus() {
         $rowCount.html("");
    }

    function clearWaitStatus() {
         $rowCount.html("");
    }

    function setWaitStatus() {
         $rowCount.html("Please wait ... this may take a while, the more data, the longer!");
    }

    function setResultStatus() {
	    $rowCount.html("<b>" + DATA.rowCount + " Results found</b>");
    }

    function showFilterForm() {
        var htm = getFilterFormHtm();
        $filter.html(htm);
    }

    function getFilterFormHtm() {
        var htm = "";
        htm += "<table class='params'>";
        htm += "  <tr>";
        htm += "    <td>";
        htm += "      <input class='tenderId' type='text' title='Tender-ID' value=''>";
        htm += "    </td>";
        htm += "    <td>";
        htm += "      <input class='contractStatus' type='text' title='Contract Status' value=''>";
        htm += "    </td>";
        htm += "    <td>";
        htm += "    </td>";
        htm += "    <td>";
        htm += "    </td>";
        htm += "    <td style='text-align: right'><div class='button textButton search'>Search</td>";
        htm += "  </tr>";
        htm += "  <tr>";
        htm += "    <td>";
        htm += "      <input class='organizationId' type='text' title='Company-ID' value=''>";
        htm += "    </td>";
        htm += "    <td>";
        htm += "      <input class='serviceType' type='text' title='Company Type' value=''>";
        htm += "    </td>";
        htm += "    <td>";
        htm += "      <input class='serviceName' type='text' title='Company Name' value=''>";
        htm += "    </td>";
        htm += "  </tr>";
        htm += "  <tr>";
        htm += "    <td>";
        htm += "      <input class='country' type='text' title='Company Country Codes' value=''>";
        htm += "    </td>";
        htm += "    <td>";
        htm += "      <input class='zip' type='text' title='Company ZIP' value=''>";
        htm += "    </td>";
        htm += "    <td>";
        htm += "      <input class='city' type='text' title='Company City' value=''>";
        htm += "    </td>";
        htm += "    <td>";
        htm += "      <input class='street' type='text' title='Company Street' value=''>";
        htm += "    </td>";
        htm += "  </tr>";
        htm += "  <tr>";
        htm += "    <td>";
        htm += "      <input class='latitude' type='text' title='Company Geo Latitude' value=''>";
        htm += "    </td>";
        htm += "    <td>";
        htm += "      <input class='longitude' type='text' title='Company Geo Longitude' value=''>";
        htm += "    </td>";
        htm += "    <td>";
        htm += "      <input class='distance' type='text' title='Company Geo Distance' value=''>";
        htm += "    </td>";
        htm += "    <td>";
        htm += "  </tr>";
        htm += "</table>";
       return htm;
    }

    function getFilter() {
        var tenderId       = $filter.find("input.tenderId").val();
        var contractStatus = $filter.find("input.contractStatus").val();
        var organizationId = $filter.find("input.organizationId").val();
        var serviceType    = $filter.find("input.serviceType").val();
        var serviceName    = $filter.find("input.serviceName").val();
        var country        = $filter.find("input.country").val();
        var zip            = $filter.find("input.zip").val();
        var city           = $filter.find("input.city").val();
        var street         = $filter.find("input.street").val();
        var latitude       = $filter.find("input.latitude").val();
        var longitude      = $filter.find("input.longitude").val();
        var distance       = $filter.find("input.distance").val();

        var jsn = {"tenderId": tenderId, "contractStatus": [ contractStatus ],
                       "offset": 0, "next": 10,
                       "organizationId": organizationId, "serviceType": serviceType, "serviceName": serviceName,
                       "country": [ country ], "zip": zip, "city": city, "street": street,
                       "geo": { "latitude": latitude, "longitude": longitude, "distance": distance }};

        return jsn;
    }

    function showSubRows($tr) {
        $tr.find("div.showSubRows").removeClass("showSubRows").addClass("hideSubRows");
        showSubRows_($tr);
    }

    function showSubRows_($tr_) {
        if (hasNextRow($tr_)) {
            var $tr = $tr_.next();
            if (! $tr.hasClass("sub")) return;
            $tr.removeClass("hide");
            showSubRows_($tr);
        }
    }

    function hasNextRow($tr) {
        return $tr.next("tr").length > 0;
    }

    function hasSubRows($tr) {
        if (hasNextRow($tr)) {
            if ($tr.next().hasClass("sub")) {
                return true;
            }
        }
        return false;
    }

    function hideSubRows($tr) {
        $tr.find("div.hideSubRows").removeClass("hideSubRows").addClass("showSubRows");
        hideSubRows_($tr);
    }

    function hideSubRows_($tr_) {
        if (hasNextRow($tr_)) {
            var $tr = $tr_.next();
            if (! $tr.hasClass("sub")) return;
            $tr.addClass("hide");
            hideSubRows_($tr);
        }
    }

    function getSelectedRows() {
        var rowIds = "";

        var $tds = DATA.gui.parent.find(".rowSelector");
        if ($tds.length == 0) {
            return "";
        }

        for (var i = 0; i < $tds.length; i++) {
            var $td = $($tds[i]);
            if ($td.html() == "x") {
                if (rowIds != "") {
                    rowIds += " ";
                }
                rowIds += $td.parent().attr("data-row-id");
            }
        }

        return rowIds;
    }

    function bindRowPager() {
        ROWPAGER.bind(ACTION.pageToRow, $rowPager);
    }

    function clearResult() {
        ROWPAGER.reset();
        $result.html("");
    }

    function viewPage() {
        var s = new Date();

        ROWPAGER.clear();
        var htm = getTableHtml();
          $result.html(htm);
        ROWPAGER.render(DATA.rowCount);

        util.log.duration(s, "quickFS: viewPage");
    }

    function getTableHtml() {
        var htm = "";

        htm += "<table data-tender-id='" + DATA.tenderId + "'>";
        htm += getHeaderHtml();
        if (DATA.page.rows.size > 0) {
            htm += getRowsHtml();
            htm += getFooterHtml();
        }
        htm += "</table>";
        return htm;
    }

    function getRowsHtml() {
        var htm = "";
        var i = 0;
        DATA.page.rows.forEach(function(row, organizationId) {
            DATA.organizationId = organizationId;
            htm += getRowHtml(row, i);
            i++;
        }, DATA.page.rows);
        return htm;
    }

    function getRowHtml(row, rowCount) {
        var htm = "";

        htm += getMainRowHtml(row, rowCount);
        if (row.sub) {
            htm += getSubRowsHtml(row);
        }
        return htm;
    }

    function writeSubRows($tr) {
        var htm = getSubRowsHtml(DATA.page.rows.get(DATA.organizationId));
        $(htm).insertAfter($tr);
        showSubRows($tr);
    }

    function getSubRowsHtml(rows) {
        var htm = "";

        for (var tenderId in rows) {
            if (tenderId !== DATA.filter.tenderId) {
                var tenderRow = rows[tenderId];
                htm += getSubRowHtml(tenderRow);
            }
        }
        return htm;
    }

    function getSubRowHtml(tenderRow) {
        var htm = "";

        htm += "<tr class='row sub hide'>";
        htm += "<td></td>";
        htm += "<td></td>";
        var columns = DATA.definition.columns;
        for (var i = 0; i < columns.length; i++) {
            var column = columns[i];
            htm += getCellHtml(tenderRow, column, false) ;
        }
        htm += "</tr>";
        return htm;
    }

    function getMainRowHtml(row, rowCount) {
        var styleClass = "row";
        if (rowCount%2 === 0) styleClass += " odd";

        var htm = "";
        htm += "<tr class='" + styleClass + "' data-row-id='" + DATA.organizationId + "'>";
        htm += "<td class='cell'>";
        htm += "  <div class='action showContract'>&nbsp;</div>";
        htm += "  <div class='action showSubRows'>&nbsp;</div>";
        htm += "</td>";
//        htm += "<td class='cell action boolean rowSelector'></td>";                            // row selector
        htm += "<td class='cell rowSelector'></td>";                                             // dummy row selector without event

        var columns = DATA.definition.columns;
        for (var i = 0; i < columns.length; i++) {
            var column = columns[i];
            htm += getCellHtml(row[DATA.filter.tenderId], column, true) ;
        }
        htm += "</tr>";
        return htm;
    }

    function getCellHtml(row, column, renderMainRowCell) {
        var htm = "";

        var cell = row.columns[column.id];

        if (column.id == "popup") {
            htm += renderCellPopup(cell, column, renderMainRowCell);
        } else if (column.id == "boolean") {
            htm += renderCellBoolean(cell, column, renderMainRowCell);
        } else if (column.type == "3") {
            htm += renderCellKpi(cell, column);
        } else {
            htm += renderCell(cell, column);
        }
        return htm;
    }

    function renderCellKpi(cell, column) {
        var styleClass = "cell";

        var cellValue = getKpiValue(cell, column);

        var htm = renderCellReadOnly(column.id, styleClass, cellValue);
        return htm;
    }

    function getKpiValue(cell, column) {
        var value = "";
        if (cell) {
            switch (column.functionType) {
            case KPI_TYPE_HIGHEST_VALUE:
                value = getMaxValue(cell.valueMap);
                break;
            case KPI_TYPE_LOWEST_VALUE:
                value = getMinValue(cell.valueMap);
                break;
            case KPI_TYPE_HIGHEST_VALUE_WITH_DURATION:
                value = getLongestDurationOfMaxValue(cell.valueMap);
                break;
            case KPI_TYPE_VALUE_WITH_LONGEST_DURATION:
                value = getValueWithLongestTotalDuration(cell.valueMap);
                break;
            case KPI_TYPE_AVERAGE_VALUE:
                value = getAverageValue(cell.valueMap);
                break;
            case KPI_TYPE_WEIGHTED_AVERAGE:
                value = getWeightedAverageValue(cell.valueMap);
                break;
            case KPI_TYPE_COUNT_DATES:
                value = getNumberOfDatesValue(cell.valueMap);
                break;
            case KPI_TYPE_COUNT_ROWS:
                value = getNumberOfRowsValue(cell.valueMap);
                break;
            case KPI_TYPE_WEIGHTED_AVERAGE_MULTIPLE_TABLES:
                value = getWeightedAverageValue(cell.valueMap);
                break;
            case KPI_TYPE_EITHER_OR:
                value = getEitherOrValue(cell.valueMap);
                break;
            case KPI_TYPE_PERCENTAGE:
                value = getPercentageValue(cell.valueMap);
                break;
            default:
                value = "Unknown KPI type: " + column.functionType;
                break
            }
        }
        return value;
    }

    function getMaxValue(valueMap) {
        var maxValue;
        if (valueMap && Object.keys(valueMap).length > 0) {
            for (var rowIndex in valueMap) {
                if (rowIndex && valueMap[rowIndex].length == 1) {
                    var value = getNumber(valueMap[rowIndex][0].depictedValue, undefined);
                    if (value) {
                        if (!maxValue || value > maxValue) {
                            maxValue = value;
                        }
                    }
                }
            }
        }
        return maxValue ? maxValue : "";
    }

    function getMinValue(valueMap) {
        var minValue;
        if (valueMap && Object.keys(valueMap).length > 0) {
            for (var rowIndex in valueMap) {
                if (rowIndex && valueMap[rowIndex].length == 1) {
                    var value = getNumber(valueMap[rowIndex][0].depictedValue, undefined);
                    if (value) {
                        if (!minValue || value < minValue) {
                            minValue = value;
                        }
                    }
                }
            }
        }
        return minValue ? minValue : "";
    }

    function getValueWithLongestTotalDuration(valueMap) {
        var valueDurationMap = {};
        var value;
        var longestDuration;
        if (valueMap && Object.keys(valueMap).length > 0) {
            for (var rowIndex in valueMap) {
                if (rowIndex && valueMap[rowIndex].length == 3) {
                    var day1 = getNumber(valueMap[rowIndex][0].depictedValue, 0);
                    var day2 = getNumber(valueMap[rowIndex][1].depictedValue, day1);
                    var duration = Math.abs(day1 - day2) + ONE_DAY_IN_MILLIS;
                    var durationValue = getNumber(valueMap[rowIndex][2].depictedValue, undefined);
                    if (durationValue && duration > 0) {
                        if (!valueDurationMap[durationValue]) {
                            valueDurationMap[durationValue] = 0;
                        }
                        valueDurationMap[durationValue] += duration;
                        if (!longestDuration || valueDurationMap[durationValue] > longestDuration) {
                            longestDuration = valueDurationMap[durationValue];
                            value = durationValue;
                        }
                    }
                }
            }
        }
        return (value === undefined || longestDuration === undefined)
               ? ""
               : value + " ; " + Math.round(longestDuration / ONE_DAY_IN_MILLIS);
    }

    function getAverageValue(valueMap) {
        var totalValue = 0;
        var numberOfValues = 0;
        if (valueMap && Object.keys(valueMap).length > 0) {
            for (var rowIndex in valueMap) {
                if (rowIndex && valueMap[rowIndex].length == 1) {
                    var value = getNumber(valueMap[rowIndex][0].depictedValue, undefined);
                    if (value) {
                        totalValue += value;
                        numberOfValues++;
                    }
                }
            }
        }
        return (numberOfValues > 0) ? Math.round(totalValue / numberOfValues) : "";
    }

    function getWeightedAverageValue(valueMap) {
        var totalNumberOfDays = 0;
        var totalWeighted = 0;
        if (valueMap && Object.keys(valueMap).length > 0) {
            for (var rowIndex in valueMap) {
                if (rowIndex && valueMap[rowIndex].length == 3) {
                    var day1 = getNumber(valueMap[rowIndex][0].depictedValue, 0);
                    var day2 = getNumber(valueMap[rowIndex][1].depictedValue, day1);
                    var duration = Math.abs(day1 - day2);
                    var numberOfDays = Math.round((duration + ONE_DAY_IN_MILLIS) / ONE_DAY_IN_MILLIS);
                    totalNumberOfDays += numberOfDays;
                    var value = getNumber(valueMap[rowIndex][2].depictedValue, undefined);
                    if (value) {
                        totalWeighted += value * numberOfDays;
                    }
                }
            }
        }
        return (totalNumberOfDays != 0 && totalWeighted != 0)
               ? Math.round(totalWeighted / totalNumberOfDays * 100) / 100
               : "";
    }

    function getNumberOfDatesValue(valueMap) {
        var totalDuration = 0;
        if (valueMap && Object.keys(valueMap).length > 0) {
            for (var rowIndex in valueMap) {
                if (rowIndex && valueMap[rowIndex].length == 2) {
                    var day1 = getNumber(valueMap[rowIndex][0].depictedValue, undefined);
                    var day2 = getNumber(valueMap[rowIndex][1].depictedValue, undefined);
                    if (day1 && day2) {
                        var duration = Math.abs(day1 - day2);
                        totalDuration += duration + ONE_DAY_IN_MILLIS;
                    }
                }
            }
        }
        return (totalDuration != 0) ? Math.round(totalDuration / ONE_DAY_IN_MILLIS) : "";
    }

    function getNumberOfRowsValue(valueMap) {
        return (valueMap && Object.keys(valueMap).length > 0) ? Object.keys(valueMap).length : "";
    }

    function getEitherOrValue(valueMap) {
        var value = "";
        if (valueMap && Object.keys(valueMap).length == 1) {
            for (var rowIndex in valueMap) {
                if (rowIndex && valueMap[rowIndex].length == 1) {
                    value = valueMap[rowIndex][0].depictedValue;
                }
            }
        }
        return value;
    }

    function getNumber(value, defaultValue) {
        var num = defaultValue;
        if (value) {
            var num = Number(value);
            if (isNaN(num)) {
                num = defaultValue;
            }
        }
        return num;
    }

    function renderCell(cell, column) {
        var styleClass = "cell";

        var htm = "";
        if (column.type == 4 && column.id == "#{messages.contract_status}") {
            htm = renderContractStatus(column.id, styleClass, cell.depictedValue);
        } else if (cell.readOnly == undefined || cell.readOnly) {
            htm = renderCellReadOnly(column.id, styleClass, cell.depictedValue);
        } else {
            htm = renderCellInput(column.id, styleClass + " qfsEditable",
                                  cell.answerId, cell.organizationId, cell.processStepFormId, cell.questionId,
                                  cell.tenderId, cell.value, cell.depictedValue);
        }
        return htm;
    }

    function renderContractStatus(columnId, styleClass, cellValue) {
        var actionMap = CONTRACT_STATUS.render(DATA.tenderId, DATA.organizationId);
        var htm = "";
        htm += "<td class='" + styleClass + "' data-column-id='" + columnId + "'>";
        htm += "<table>";
        htm += "<tr><td colspan='15'>" + cellValue + "</td></tr>";
        htm += "<tr><td colspan='15'>&nbsp;</td></tr>";
        htm += "<tr><td>";
        for (var action in actionMap) {
            var render = actionMap[action];
            if (render) {
                htm += "<div class='action contractStatus-common contractStatus-" + action + "'>&nbsp;</div>";
            }
        }
        htm += "</td></tr>";
        htm += "</table>";
        htm +="</td>";
        return htm;
    }

    function renderCellReadOnly(columnId, styleClass, cellValue) {
        var htm = "";
        htm += "<td class='" + styleClass + "' data-column-id='" + columnId + "'>";
        htm += cellValue;
        htm +="</td>";
        return htm;
    }

    function renderCellInput(columnId, styleClass,
                             answerId, organizationId, processStepFormId, questionId, tenderId, value, depictedValue) {
        var htm = "";
        //htm += "<td class='" + styleClass + "' data-column-id='" + columnId + "' style='background: green;'>";
        htm += "<td";
        htm += " data-column-id='" + columnId + "'";
        htm += " data-answer-id='" + answerId + "'";
        htm += " data-organization-id='" + organizationId + "'";
        htm += " data-process-step-form-id='" + processStepFormId + "'";
        htm += " data-question-id='" + questionId + "'";
        htm += " class='" + styleClass;
        var inputHtm = "";
        var question = CONVERT.getQuestion(tenderId, questionId);
        switch (question.questType) {
            case FIELD_TYPE_STRING:
                htm += " data-type-String'"
                htm += " data-value='" + value + "'";
                inputHtm += "<input type='text' value='" + depictedValue + "'/>";
                break;
            case FIELD_TYPE_TEXT:
                htm += " data-type-Text'"
                htm += " data-value='" + value + "'";
                inputHtm += "<textarea rows='8' cols='70'>" + depictedValue + "</textarea>";
                break;
//            case FIELD_TYPE_CHECKBOX:
//                htm += " data-type-Boolean'"
//                htm += " data-value='" + (value == "Yes" ? true : false) + "'";
//                inputHtm += "<div>&nbsp;</div>";
//                break;
            case FIELD_TYPE_CHECKBOX:
                htm += " data-type-SingleSelection'"
                htm += " data-value='" + value + "'";
                var questionMap = {};
                questionMap[true] = {};
                questionMap[true].questValue = value ? value : question.questValue;
                questionMap[true].propName = util.message.get("yes");
                questionMap[false] = {};
                questionMap[false].questValue = value ? value : question.questValue;
                questionMap[false].propName = util.message.get("no");
                inputHtm += getSingleSelection(questionMap, value, false);
                break;
//            case FIELD_TYPE_LRA:
//                htm += " data-type-Boolean'"
//                htm += " data-value='" + (value == "Non LRA" ? false : true) + "'";
//                inputHtm += "<div>&nbsp;</div>";
//                break;
            case FIELD_TYPE_LRA:
                htm += " data-type-SingleSelection'"
                htm += " data-value='" + value + "'";
                var questionMap = {};
                questionMap[true] = {};
                questionMap[true].questValue = value ? value : question.questValue;
                questionMap[true].propName = util.message.get("lra");
                questionMap[false] = {};
                questionMap[false].questValue = value ? value : question.questValue;
                questionMap[false].propName = util.message.get("non_lra");
                inputHtm += getSingleSelection(questionMap, value, false);
                break;
//                htm += " data-type-Radio'"
//                htm += " data-value='" + value + "'";
//                inputHtm += getRadio(tenderId, questionId, value, organizationId);
//                break;
            case FIELD_TYPE_CANCELLATION_PARAMETERS:
                htm += " data-type-SingleSelection'"
                htm += " data-value='" + value + "'";
                var questionMap = CONVERT.getQuestions(tenderId, questionId);
                inputHtm += getSingleSelection(questionMap, value, false);
                break;
            case FIELD_TYPE_RADIO:
                htm += " data-type-SingleSelection'"
                htm += " data-value='" + value + "'";
                var questionMap = CONVERT.getQuestions(tenderId, questionId);
                inputHtm += getSingleSelection(questionMap, value, true);
                break;
            default:
                htm += " data-type-" + question.questType + "'";
                htm += " data-value='" + value + "'";
                break;
        }
        htm += ">";
        htm += inputHtm;
        htm +="<div class='showAnswerHistoryButton'/>";
        htm +="</td>";
        return htm;
    }

    function getRadio(tenderId, questionId, value, organizationId) {
        var html = "";
        html += "<table><tbody><tr>";
        var questions = CONVERT.getQuestions(tenderId, questionId);
        var name = organizationId + "_" + questionId;
        for (var propId in questions) {
            var question = questions[propId];
            var propName = question.propName;
            if (propName === value) {
                html += "<td data-value='" + propId + "'><input type='radio' name='" + name + "' value='" + propId + "' checked='true'>" + propName + "</input></td>";
            } else {
                html += "<td data-value='" + propId + "'><input type='radio' name='" + name + "' value='" + propId + "'>" + propName + "</input></td>";
            }
        }
        html += "</tr></tbody></table>";
        return html;
    }

    function getSingleSelection(questionMap, value, vertical) {
        var html = "";
        html += "<table>";
        html += vertical ? "<tr>" : "";
        for (var propId in questionMap) {
            var question = questionMap[propId];
            var selectedValue = value ? value : question.questValue;
            var propName = question.propName;
            html += vertical ? "" : "  <tr>";
            if (propId === selectedValue) {
                html += "<td data-value='" + propId + "' data-selected='true'>" + propName + "</td>";
            } else {
                html += "<td data-value='" + propId + "' data-selected='false'>" + propName + "</td>";
            }
            html += vertical ? "" : "</tr>";
        }
        html += vertical ? "</tr>" : "";
        html += "</table>";
        return html;
    }

    function getValue($td) {
        return $td.attr("data-value");
    }

    function setValue($td, value) {
        $td.attr("data-value", value);
    }

    function renderCellPopup(cell, column, renderMainRowCell) {
        var styleClass = "cell ";
        if (renderMainRowCell) styleClass += " action popup";

        var cellValue = "";
        if (cell) cellValue = cell.value;

        // todo parameter for popup call

        var htm = "";
        htm += "<td class='" + styleClass + "' data-column-id='" + column.id + "'>";
        htm += cellValue;
        htm +="</td>";
        return htm;
    }

    function renderCellBoolean(cell, column, renderMainRowCell) {
        var styleClass = "cell ";
        if (renderMainRowCell) styleClass += " action boolean";

        var cellValue = "";
        if (cell && !cell.value) cellValue = "x";

        var htm = "";
        htm += "<td class='" + styleClass + "' data-column-id='" + column.id + "'>";
        htm += cellValue;
        htm +="</td>";
        return htm;
    }

    function getFooterHtml() {
        var htm = "";

        htm += "<tr class='columnFooter'>";
        htm += "<th></th>";
        htm += "<th></th>";
        var columns = DATA.definition.columns;
        for (var i = 0; i < columns.length; i++) {
            var column = columns[i];
            htm += "<th>" + column.caption + "</th>";
        }
        htm += "</tr>";
        return htm;
    }

    function getHeaderHtml() {
        var htm = "";

        htm += "<tr class='columnHeader'>";
        htm += "<th></th>";
        htm += "<th class='action selectAllRows'></th>";
        var columns = DATA.definition.columns;
        for (var i = 0; i < columns.length; i++) {
            var column = columns[i];
            htm += "<th data-column-id='" + column.id + "'>";
            htm += column.caption;
            if (column.sortable == true) {
                if (isOrdered(column.id)) {
                    htm += "<div class='action button order active'></div>";
                } else {
                    htm += "<div class='action button order'></div>";
                }
                if (isOrderedDesc(column.id)) {
                    htm += "<div class='action button orderDesc active'></div>";
                } else {
                    htm += "<div class='action button orderDesc'></div>";
                }
            }
            htm += "</th>";
        }
        htm += "</tr>";
        return htm;
    }

    function isOrderedDesc(columnId) {
        if (DATA.page.sort) {
            if (DATA.page.sort.active) {
                if (DATA.page.sort.desc) {
                    if (DATA.page.sort.id == columnId) return true;
                }
            }
        }
        return false
    }

    function isOrdered(columnId) {
        if (DATA.page.sort) {
            if (DATA.page.sort.active) {
                if (!DATA.page.sort.desc) {
                    if (DATA.page.sort.id == columnId) return true;
                }
            }
        }
        return false
    }

    function initStructure() {
        var htm = "";
        htm += '<div class="filter"></div>';
        htm += '<br />';
        htm += '<div class="rowCount"></div>';
        htm += '<br />';
        htm += '<div class="result"></div>';
        htm += '<div class="rowPager"></div>';

        $parent = $(DATA.guiParentSelector).first();
        $parent.addClass("quickFS");
        $parent.html(htm);

        $filter = $parent.find(".filter");
        $rowCount = $parent.find(".rowCount");
        $result = $parent.find(".result");
        $rowPager = $parent.find(".rowPager");
    }

    function init(quickFS) {
        DATA = quickFS.DATA;
        CONVERT = quickFS.INTERFACE_CONVERT;
        CONTRACT_STATUS = quickFS.CONTRACT_STATUS;
        ACTION = quickFS.ACTION;
        ROWPAGER = quickFS.GUI_ROWPAGER;
        initStructure();
    }

}
