var readSelector = 'read';
var writeSelector = 'write';
var gridElement = '#test-grid tbody tr input:checkbox';

function setReadSelectorTo(newValue)
{
    readSelector = newValue;
}

function setWriteSelectorTo(newValue)
{
    writeSelector = newValue;
}

function setGridElement(newValue)
{
    gridElement = newValue;
}

function setAllUsedReadCheckBoxesToTrue(readSelector, writeSelector) {
    $('.' + writeSelector).each(function (i, e) {
        var readCheckBox = $(e).parent().parent().find('.' + readSelector);
        if (e.checked) {
            readCheckBox.attr("disabled", true);
            readCheckBox.attr("checked", true);
        }
    });
}

$(gridElement).change(function ()
{
    var thisElement = $(this).parent().parent();
    var nextElement = thisElement.next();

    var permissionType = $(this).attr('class');

    var nextElementRecLevel = 0;
    var startRecLevel = thisElement.find('td:first-child').text().split(' ')[0].length;
    var isChecked = $(this).is(':checked');

    do {
        nextElementRecLevel = nextElement.find('td:first-child').text().split(' ')[0].length;
        if (nextElementRecLevel <= startRecLevel || nextElementRecLevel === false) {
            processChildData(thisElement, nextElement, permissionType, isChecked, false);
            break;
        } else {
            processParentData(thisElement, nextElement, permissionType, isChecked);
        }
        thisElement = nextElement;
        nextElement = thisElement.next();
    } while (nextElement.attr('class'));
});

function processChildData(thisElement, nextElement, permissionType, isChecked, withNextElement)
{
    if (permissionType === writeSelector) {
        processChildDataWithWritePermission(thisElement, nextElement, isChecked, withNextElement, readSelector);
    } else {
        processChildDataWithoutWritePermission(thisElement);
    }
}

function processChildDataWithWritePermission(thisElement, nextElement, isChecked, withNextElement, readSelector)
{
    if (isChecked) {
        processDisabledAttrToReadElement(thisElement, nextElement, isChecked, withNextElement, readSelector);
    } else {
        processRemoveAttrFromReadElement(thisElement, nextElement, withNextElement, readSelector);
    }
    processCheckedAttrToReadElement(thisElement, nextElement, isChecked, withNextElement, readSelector);
}

function processDisabledAttrToReadElement(thisElement, nextElement, isChecked, withNextElement, readSelector)
{
    addAttributeToElement(thisElement, readSelector, 'disabled', isChecked, true);
    if (withNextElement === true) {
        addAttributeToElement(nextElement, readSelector, 'disabled', isChecked, true);
    }
}

function processRemoveAttrFromReadElement(thisElement, nextElement, withNextElement, readSelector)
{
    removeAttributeFromElement(thisElement, readSelector, 'disabled', true);
    if (withNextElement === true) {
        removeAttributeFromElement(nextElement, readSelector, 'disabled', true);
    }
}

function processCheckedAttrToReadElement(thisElement, nextElement, isChecked, withNextElement, readSelector)
{
    addAttributeToElement(thisElement, readSelector, 'checked', isChecked, false);
    if (withNextElement === true) {
        addAttributeToElement(nextElement, readSelector, 'checked', isChecked, false);
    }
}

function addAttributeToElement(element, readSelector, attribute, value, addValueToHiddenField)
{
    element.find('.' + readSelector).attr(attribute, value);
    processAttrValueToHiddenField(element, addValueToHiddenField);
}

function removeAttributeFromElement(element, readSelector, attribute, addValueToHiddenField)
{
    element.find('.' + readSelector).removeAttr(attribute);
    processAttrValueToHiddenField(element, addValueToHiddenField);
}

function processAttrValueToHiddenField(element, addValueToHiddenField)
{
    if (addValueToHiddenField === true) {
        addAttrValueToHiddenField(element);
    }
}

function addAttrValueToHiddenField(element)
{
    element.find('input:hidden').attr('value', '0');
}

function processChildDataWithoutWritePermission(thisElement)
{
    if (thisElement.find('.' + writeSelector).attr('checked') === 'checked') {
        addAttributeToElement(thisElement, readSelector, 'disabled', 'disabled', true);
        addAttributeToElement(thisElement, readSelector, 'checked', 'checked', false);
    }
}

function processParentData(thisElement, nextElement, permissionType, isChecked)
{
    processChildData(thisElement, nextElement, permissionType, isChecked, true);
    processChildDataWithWritePermission(nextElement, nextElement, isChecked, false, permissionType);
}