var VRSFocusedId = null;
var SRSSelectType = 'select-one';
var SRSCheckBoxType = 'checkbox';

var VRSRatingError = '';
var VRSRefreshing = false;
var VRSInputHtmls = {};

var VRSLastRequestId = 0;
var VRSFirstRefresh = true;
var VRSLoadWarningsCleared = false;

var VRSLastRequestTimerId = null;

var VRSRefreshDebug = -1000;

function GetAbsLeftTop(startElement) {
    var result = [0, 0];
    element = startElement;
    while (element.nodeName != "BODY") {
        if (element == startElement || element.nodeName != 'SPAN') {
            result[0] += parseInt(element.offsetLeft);
            result[1] += parseInt(element.offsetTop);
        }
        element = element.offsetParent;
    }
    return result;
}

function SetInputHtml(cell, inputHtml) {
    var id = cell.id;
    var result = VRSInputHtmls[id] == "";
    if (VRSInputHtmls[id] != inputHtml) {
        VRSInputHtmls[id] = inputHtml;
        cell.innerHTML = inputHtml;
    }
    return result; // returns true if cell was empty
}

function GetCurrentForm() {
    return document.forms[0];
}

function GetInputById(id) {
    return document.getElementById(ValueIdPrefix + id.toString());
}

function GetInputCellById(id) {
    return document.getElementById(InputCellIdPrefix + id.toString());
}

function GetCurrentInputState() {
    var ids = []
    var vals = []
    var i = 0;
    for (i in inputStates) {
        var inputState = inputStates[i];
        var id = inputState.Id;
        ids.push(id);
        var input = GetInputById(id);
        if (input == null)
            vals.push(InvisiblePrefix);
        else
            vals.push(VisiblePrefix + GetInputValue(input));
    }
    return [ids.join(','), vals.join('\t')].join(';');
}

function GetInputState(id) {
    var i;
    for (i in inputStates) {
        inputState = inputStates[i];
        if (inputState.Id == id)
            return inputState;
    }
    return null;
}

var rsvPassword = 0;

function CreateInputElement(id, container) {
    var tabIndexStr = ' tabindex="' + container.getAttribute('rs_tabindex') + '"';
    var inputState = GetInputState(id);
    var inputId = '"' + ValueIdPrefix + id + '"';
    if (inputState.IsBoolean)
        return '<input type="checkbox" onclick="ElementChanged()" id=' + inputId + tabIndexStr + '>'
                + '<label id="' + DescIdPrefix + id + '" for=' + inputId + '></label>';

    var choices = inputState.Choices;
    if (choices.length == 0) {
        elementType = 'input';
        choiceHtml = "";
        creationArgs = ' onkeydown="ElementKeyDown()"';
        if (id == rsvPassword)
            creationArgs += ' type="password"';
    } else {
        elementType = 'select';
        choiceHtml = "<option>" + choices.join("</option><option>") + "</option>";
        creationArgs = ' class="RSLWebValueListInputSelect"';
    }
    return '<' + elementType + creationArgs + ' id=' + inputId + tabIndexStr + ' '
      + 'onblur="ElementUnfocused(event)" onfocus="ElementFocused(event)" '
      + 'onChange="ElementChanged()">'
      + choiceHtml + '</' + elementType + '>';
}

function SetSelectedItem(selectElement, value) {
    var i;
    for (i = 0; i < selectElement.options.length; i++) {
        var option = selectElement.options[i];
        option.selected = option.text == value;
    }
}

function GetSelectedItem(selectElement) {
    var i;
    for (i = 0; i < selectElement.options.length; i++) {
        var option = selectElement.options[i];
        if (option.selected)
            return option.text;
    }
    return "";
}

function GetInputValue(input) {
    if (input.type == SRSSelectType)
        return GetSelectedItem(input);
    else if (input.type == SRSCheckBoxType) {
        if (input.checked)
            return 'T';
        else
            return 'F';
    } else
        return input.value;
}

function SetInputValue(input, value) {
    if (input.type == SRSSelectType)
        SetSelectedItem(input, value);
    else if (input.type == SRSCheckBoxType)
        input.checked = value == 'T';
    else {
        if (input.value != value)
            input.value = value;
    }
}

function SetRowVisible(id, visible) {
    var row = document.getElementById(id);
    if (row != null)
        row.style.display = visible ? '' : 'none';
}

function RefreshOutputs(outputs) {
    for (i = 0; i < outputs.length; i++) {
        SetRowVisible(RowIdPrefix + outputs[i].Id, true);

        var displayElement = document.getElementById(ValueIdPrefix + outputs[i].Id);
        if (displayElement != null)
            displayElement.innerHTML = outputs[i].ReportString;
    }
    RefreshCustomOutputs(outputs);
}

function ReplaceCssClass(element, addClass, dropClass) {
    var classes = element.className.split(' ');
    var found = false;
    for (i = 0; i < classes.length; i++) {
        if (classes[i] == dropClass) {
            classes[i] = addClass;
            found = true;
        }
    }
    var newClassName = classes.join(' ').replace(/ +/, ' ');
    if (!found)
        newClassName += ' ' + addClass;
    element.className = newClassName;
}

function RefreshState_CallBack(response) {
    if ((VRSRefreshDebug > -1000) && (VRSRefreshDebug <= -700)) {
        VRSRefreshDebug = VRSRefreshDebug - 1;
    } else 
        VRSRefreshDebug = -700;
    // On Opera browser, sometimes response comes back after
    // the page has been refreshed and response isn't needed anymore
    if (response.value == null)
        return;

    var initialFocusTabIndex = null;
    var initialFocusId = '';

    VRSRefreshDebug = -500;
    VRSRefreshing = true;
    try {
        if (response.value.RequestId != VRSLastRequestId)
            return;
        inputStates = response.value.InputStates;

        VRSRefreshDebug = -100;
        for (i in inputStates) {
            VRSRefreshDebug = i;
            var inputState = inputStates[i];
            var id = inputStates[i].Id;
            var inputCell = GetInputCellById(id);
            var visible = !inputState.IsHidden;

            SetRowVisible(RowIdPrefix + id, visible);
            if (visible) {
                if (VRSFocusedId == null)
                    VRSFocusedId = id;

                wasEmpty = SetInputHtml(inputCell, CreateInputElement(id, inputCell));

                var label = document.getElementById(DescIdPrefix + id);
                var desc = inputState.Description;
                if (!inputState.IsBoolean)
                    desc += ':';
                label.innerHTML = desc;

                var inputControl = GetInputById(id);
                if (VRSFirstRefresh || wasEmpty || id != VRSFocusedId)
                    SetInputValue(inputControl, inputState.Value);

                if (!inputState.IsBoolean) {
                    if (inputState.IsValid)
                        ReplaceCssClass(inputControl, 'validInput', 'invalidInput');
                    else
                        ReplaceCssClass(inputControl, 'invalidInput', 'validInput');
                }

                if (VRSFirstRefresh && (initialFocusTabIndex == null
                        || initialFocusTabIndex > inputCell.getAttribute('rs_tabindex'))) {
                    initialFocusTabIndex = inputCell.getAttribute('rs_tabindex');
                    initialFocusId = id;
                }
            } else
                SetInputHtml(inputCell, "");
        }

        VRSRefreshDebug = 1000;
        RefreshOutputs(response.value.Outputs);
        
        VRSRefreshDebug = 1001;
        DisplayLoadWarnings(response.value.LoadWarnings);
        
        VRSRefreshDebug = 1002;
        ProcessExtraData(response.value.ExtraData);
        
        VRSRefreshDebug = 1003;
        VRSRatingError = response.value.ErrorMsg;
        VRSFirstRefresh = false;
        if(window.AfterRefreshState) {
            AfterRefreshState();
        }
        
        VRSRefreshDebug = 1004;
        RefreshTipAndError();
        RecenterPage();

        VRSRefreshDebug = 1005;
        if (initialFocusId != '') {
            document.getElementById(ValueIdPrefix + initialFocusId).focus();
        }
    } finally {
        VRSRefreshing = false;
    }
}

function RequestInputStateRefresh() {
    if (VRSRefreshing)
        return;

    if (VRSLastRequestTimerId != null)
        self.clearTimeout(VRSLastRequestTimerId);

    VRSLastRequestTimerId = self.setTimeout("ImmediateRequestStateRefresh();", 500);
}

function FirstTimeRequestStateRefresh() {
    ImmediateRequestStateRefresh();
    if (navigator.userAgent.indexOf("Firefox") > -1)
        RequestInputStateRefresh();
}

function ElementUnfocused(event) {
    RequestInputStateRefresh(false);
    if (VRSRefreshing)
        return;

    var input = event.srcElement != null ? event.srcElement : event.target;
    if (VRSFocusedId == Deprefix(input.id)) {
        DisplayTip('');
        VRSFocusedId = null;
    }
}

function ElementFocused(event) {
    if (VRSRefreshing)
        return;

    var input = event.srcElement != null ? event.srcElement : event.target;
    VRSFocusedId = Deprefix(input.id);
    RefreshTipAndError();
}

function Deprefix(idStr) {
    return idStr.slice(2); // strip off two char input/row/label prefix
}

function RefreshTipAndError() {
    var i;
    var allValid = VRSRatingError == "";
    var errorMsg = VRSRatingError;
    for (i in inputStates) {
        inputState = inputStates[i];
        allValid = allValid && inputState.IsValid;
        if (inputState.Id == VRSFocusedId) {
            if (inputState.ErrorMsg != '')
                errorMsg = inputState.ErrorMsg;
            DisplayTip("<b>" + inputState.Description + "</b><br/>" + inputState.Tip);
        }
    }
    if (!allValid && errorMsg == "")
        errorMsg = "Not all inputs are valid; please select a highlighted input for more information.";
    DisplayError(errorMsg);
}

function HandleRefreshError(errorDesc) {
    if (errorDesc.indexOf("Response") <= -1) //exclude nuisance "Response is not available in this context" messages. NOT localized! But no other way to handle? Error is just generic HttpException
    	alert("Error refreshing page: " + errorDesc);
}

function ElementChanged() {
    RequestInputStateRefresh();
}

function ElementKeyDown() {
    RequestInputStateRefresh();
}

function LogEvent(text) {
    text = text.replace("&", "&amp;");
    text = text.replace("<", "&lt;");
    text = text.replace(">", "&gt;");
    log = document.createElement('SPAN');
    log.innerHTML = '\n' + text;
    GetCurrentForm().appendChild(log);
}
