﻿function AjaxDropDownTree(containerID, serviceUrl, maxSelectionCount, displayTextPattern, infoTextPattern, initialCheckedValues, bindMouseUp) {
    var _onChanged;
    var _isLoaded = false;
    
    function toggle() {
        if (!_isLoaded) {
            load();
        }
        jQuery('#' + containerID + ' .treepanel').toggle();
        jQuery('#' + containerID + ' .hackforie6').toggle();
    }
    function isLoaded() {
        return _isLoaded;
    }
    function load() {
        showLoading();
        jQuery.ajax({
            type: "GET",
            contentType: "application/json; charset=utf-8",
            url: serviceUrl,
            dataType: "json",
            success: bind
        });
    }
    function bind(data, textStatus) {
        inputName = containerID + '_input';
        jQuery('#' + containerID + ' .treecontainer').html(TreeGenerator(data, inputName, getInitialCheckedValues()).GetTreeHtml());
        jQuery('#' + containerID).find('input:checkbox').click(checkboxClick);
        jQuery('#' + containerID + ' .treecontainer').find('img').click(toggleSubNodes);
        
        hideLoading();
        jQuery('#' + containerID + ' .treecontainer').show();
        _isLoaded = true;
        
        setCheckedValues(getInitialCheckedValues());
    }
    function showCheckedCount(checkedCount) {
        var displayText = checkedCount > 0
                            ? displayTextPattern.replace('{0}', checkedCount)
                            : infoTextPattern.replace('{0}', maxSelectionCount);
        jQuery('#' + containerID + ' .displaytext').html(displayText);
    }
    function setCheckboxStatus(checkedCount) {
        if (checkedCount >= maxSelectionCount) {
            jQuery('#' + containerID).find('input:checkbox').not(':checked').attr('disabled', true);
        }
        else {
            jQuery('#' + containerID).find('input:checkbox:disabled').removeAttr('disabled');
        }
    }
    function changed() {
        var checkedCount = getCheckedCount();
        showCheckedCount(checkedCount);
        if (_isLoaded) {
            setCheckboxStatus(checkedCount);
        }
        triggerOnChanged();
    }
    function checkboxClick(sender, args) {
        if (this.checked) {
            jQuery(this).parent().find('input:checkbox').attr('checked', false);
            if (jQuery(this).parent().parent().attr('class') != 'treecontainer') {
                jQuery(this).parent().parent().find('input:checkbox:first').attr('checked', false);
            }
            jQuery(this).attr('checked', true);
        }
        changed();
    }
    function setCheckedValues(checkedValues) {
        if (!_isLoaded) {
            initialCheckedValues = checkedValues.join(',');
        }
        else {
            inputName = containerID + '_input';
            jQuery("input[name='" + inputName + "']").attr('checked', false);
            for (var i = 0; i < checkedValues.length; ++i) {
                jQuery("input[name='" + inputName + "'][value=" + checkedValues[i] + "]").attr('checked', true);
            }
            jQuery('#' + containerID + ' .treecontainer div > div').find('input:checked').parent().parent().find('div').toggle();
            jQuery('#' + containerID + ' .treecontainer div > div').find('input:checked').parent().parent().find('img').attr('src', ajaxDropDownTreeImageRootFolder + 'minus.gif');
            changed();
        }
    }
    function getCheckedValues() {
        if (!_isLoaded) {
            return initialCheckedValues;
        }
        else {
            var checkedValues = new Array();
            jQuery('#' + containerID).find('input:checkbox:checked').each(function() {
                checkedValues[checkedValues.length] = this.value;
            });
            return checkedValues.join(',');
        }
    }
    function getValue() {
        return jQuery.map(jQuery('#' + containerID).find('input:checkbox:checked'), function (item, i) {
            var $input = $(item);
            return { "Text": $input.next().text(), "Value": $input.val() };
        });
    }
    function getCheckedCount() {
        if (!_isLoaded) {
            return getInitialCheckedValues().length;
        }
        else {
            return jQuery('#' + containerID).find('input:checkbox:checked').length;
        }
    }
    function showLoading() {
        jQuery('#' + containerID + ' .treeloading').show();
    }
    function hideLoading() {
        jQuery('#' + containerID + ' .treeloading').hide();
    }
    function mouseUpFired(e) {
        if (jQuery(e.target).parents('#' + containerID).length == 0 &&
                    jQuery('#' + containerID + ' .treepanel').is(':visible')) {
            toggle();
        }
    }
    function deselectAll() {
        jQuery('#' + containerID).find('input:checkbox:checked').attr('checked', false);
        changed();
    };
    function getInitialCheckedValues() {
        return initialCheckedValues.length != 0 ? initialCheckedValues.split(',') : new Array();
    };
    function toggleSubNodes(sender, args) {
        jQuery(this).parent().find('div').toggle();
        //set image
        if (jQuery(this).attr('src').indexOf('plus') >= 0) {
            jQuery(this).attr('src', ajaxDropDownTreeImageRootFolder + 'minus.gif');
        }
        else {
            jQuery(this).attr('src', ajaxDropDownTreeImageRootFolder + 'plus.gif');
        }
    };
    function triggerOnChanged() {
        if (_onChanged != null) {
            for (var i = 0; i < _onChanged.length; i++) {
                _onChanged[i]();
            }
        }
    };
    function bindOnChanged(fn) {
        if (_onChanged == null) {
            _onChanged = new Array();
        }
        _onChanged.push(fn);
    };

    if (bindMouseUp) {
        jQuery(document).mouseup(mouseUpFired);
    }
    jQuery('#' + containerID + ' .displaypanel').click(toggle);
    jQuery('#' + containerID + ' .closebutton').click(toggle);
    jQuery('#' + containerID + ' .deselectbutton').click(deselectAll);
    showCheckedCount(getCheckedCount());
    
    this.InitialCheckedValues = initialCheckedValues;
    this.BindOnChanged = bindOnChanged;
    this.GetCheckedValues = getCheckedValues;
    this.SetCheckedValues = setCheckedValues;
    this.GetValue = getValue;
    this.Toggle = toggle;
    this.IsLoaded = isLoaded;
    return this;
}

function TreeGenerator(nodes, inputName, selectedValues) {
    function getTreeHtml() {
        return createTree();
    }
    function createTree() {
        var result = '';
        for (var i = 0; i < nodes.length; ++i) {
            if (nodes[i].ParentID == null) {
                result += generateNode(nodes[i].ID, nodes[i].Name, 0);
            }
        }
        return result;
    }
    function generateNode(value, text, depth) {
        var result = '';

        var subNodes = '';
        var subNodeCount = 0;
        for (var i = 0; i < nodes.length; ++i) {
            if (nodes[i].ParentID == value) {
                subNodes += generateNode(nodes[i].ID, nodes[i].Name, depth+1);
                subNodeCount++;
            }
        }
        if (subNodeCount > 0) {
            result += '<div>';
            result += '<img src="' + ajaxDropDownTreeImageRootFolder + 'plus.gif" border="0"/>'
        }
        else {
            if (depth == 0) {
                result += '<div style="padding-left:13px;">';
            }
            else {
                result += '<div style="padding-left:25px;display:none;">';
            }
            
        }
        result += createElement(value, text);
        result += subNodes;
        result += '</div>';
        return result;
    }
    function createElement(value, text) {
        result = '<input name=' + inputName + ' type="checkbox" value="' + value + '"/>';
        result += '<span>' + text + '</span>';
        return result;
    }
    this.GetTreeHtml = getTreeHtml;
    return this;
}
