inkinru.ContentItemTreeControl = function (id)
{
    this.id = id;
}

    inkinru.ContentItemTreeControl.prototype.create = function (config)
    {
//        console.log(config);

        if (config)
        {
            var that = this;

            inkinru.page.callServerMethod('Core', 'getCatalogs', {relatedInfo: true}, function (result) {
                if (!inkinru.page.checkAjaxResult(result))
                    return;

                that.catalogs = mapById(result.data);
            });

            this.tree = new dhtmlXTreeObject(this.id, "100%", "100%", 0);

            this.tree.setSkin('dhx_skyblue');
            this.tree.setImagePath(inkinru.page.templatePath + '/images/tree-icons/');
            this.tree.setOnClickHandler(function (itemId) {that.onClick(itemId);});
            this.tree.attachEvent('onOpenStart', function(id, state){return that.onNodeOpenStart(id, state)});


            this.loadItems(0, config.tree.children);
        }
    }

    inkinru.ContentItemTreeControl.prototype.loadItems = function (parentId, levels, parentLevel)
    {
        var that = this;
        var fn;
        var levelIndex;
        var params;
        var nodeId;

        this.tree.deleteItem(parentId + '_expandStub');

        for (levelIndex in levels)
        {
            var level = levels[levelIndex];
            var stubId = parentId + '_stub' + levelIndex;

            if (parentLevel)
                level.parent = parentLevel;

            switch (level.type)
            {
                case 'Text':
                    nodeId = this.nodeId(parentId, levelIndex, 0);

                    this.createNode(
                            0,
                            level,
                            parentId,
                            'child',
                            nodeId,
                            level.text[inkinru.page.language],
                            this.levelHasChildren(level));

                    break;

                case 'CategoryTree':
                    this.tree.insertNewChild(parentId, stubId, '');
                    this.tree.closeItem(parentId);

                    fn = function (levelIndex, level) {
                    inkinru.page.callServerMethod(
                            'Core',
                            'getCategories',
                            {tree_id: level.id},
                            function (result) {that.onLoadCategoryTree(parentId, levelIndex, level, result);});
                    };

                    fn(levelIndex, level);
                    break;

                case 'Catalog':
                    this.tree.insertNewChild(parentId, stubId, '');
                    this.tree.closeItem(parentId);

                    params = {
                            catalogId:  level.id,
                            filter:     serialize(this.getFilter(parentId, level))};

                    fn = function (levelIndex, level) {
                    inkinru.page.callServerMethod(
                            'Core',
                            'getContentItems',
                            params,
                            function (result) {that.onLoadContentItems(parentId, levelIndex, level, result);});
                    };

                    fn(levelIndex, level);
            }
        }
    }

    inkinru.ContentItemTreeControl.prototype.nodeId = function (parentId, levelIndex, inLevelIndex)
    {
        return parentId + '_l' + levelIndex + '_' + inLevelIndex;
    }

    inkinru.ContentItemTreeControl.prototype.levelHasChildren = function (level)
    {
        if (level.children)
            for (var i in level.children)
                if (!level.children[i].implied)
                    return true;

        return false;
    }

    inkinru.ContentItemTreeControl.prototype.getImpliedChildLevel = function (level)
    {
        if (level.children)
        {
            for (var i in level.children)
            {
                if (level.children[i].implied)
                {
                    level.children[i].parent = level;
                    return level.children[i];
                }
            }
        }

        return null;
    }

    inkinru.ContentItemTreeControl.prototype.onLoadCategoryTree = function (parentId, levelIndex, level, result)
    {
        if (!inkinru.page.checkAjaxResult(result))
            return;

        var i;
        var stubId = parentId + '_stub' + levelIndex;
        var previousId = stubId;
        var nodeId;

        for (i in result.data)
        {
            var category = result.data[i];

            nodeId = this.nodeId(parentId, levelIndex, i);

            this.createCategoryNode(
                    category,
                    level,
                    previousId,
                    'next',
                    nodeId);

            previousId = nodeId;
        }

        this.tree.deleteItem(stubId);
        this.tree.openItem(parentId);
    }

    inkinru.ContentItemTreeControl.prototype.onLoadContentItems = function (parentId, levelIndex, level, result)
    {
        if (!inkinru.page.checkAjaxResult(result))
            return;

        var i;
        var stubId = parentId + '_stub' + levelIndex;
        var previousId = stubId;
        var nodeId;

        for (i in result.data)
        {
            var obj = result.data[i];

            nodeId = this.nodeId(parentId, levelIndex, i);

            this.createContentItemNode(
                    obj,
                    level,
                    previousId,
                    'next',
                    nodeId);

            previousId = nodeId;
        }

        this.tree.deleteItem(stubId);
//        this.tree.closeItem(parentId);
//        this.tree.openItem(parentId);
    }

    inkinru.ContentItemTreeControl.prototype.createNode = function (objectId, level, relatedId, relation, nodeId, text, forAutoLoad)
    {
        var fn;

        switch (relation)
        {
            case 'next':
                fn = 'insertNewNext';
                break;
            case 'child':
                fn = 'insertNewChild';
        }

        this.tree[fn](
                relatedId,
                nodeId,
                text,
                0,
                'enabled.png',
                'enabled.png',
                'enabled.png');

        this.tree.setUserData(nodeId, 'level', level);
        this.tree.setUserData(nodeId, 'objectId', objectId);

        if (forAutoLoad)
        {
            this.tree.insertNewChild(nodeId, nodeId + '_expandStub', '');
            this.tree.setUserData(nodeId, 'toLoad', true);
            this.tree.closeItem(nodeId);
        }
    }

    inkinru.ContentItemTreeControl.prototype.createCategoryNode = function (category, level, relatedId, relation, nodeId)
    {
        this.createNode(
                category.id,
                level,
                relatedId,
                relation,
                nodeId,
                category.title,
                (!category.children || !category.children.length) && this.levelHasChildren(level));

        if (category.children)
        {
            for (var i in category.children)
            {
                var child = category.children[i];
                var childId = this.nodeId(nodeId, null, i);

                this.createCategoryNode(
                        child,
                        level,
                        nodeId,
                        'child',
                        childId);
            }
        }
    }

    inkinru.ContentItemTreeControl.prototype.createContentItemNode = function (contentItem, level, relatedId, relation, nodeId)
    {
        this.createNode(
                contentItem.id,
                level,
                relatedId,
                relation,
                nodeId,
                contentItem.title,
                this.levelHasChildren(level));
    }

    inkinru.ContentItemTreeControl.prototype.onClick = function (itemId)
    {
        var level = this.tree.getUserData(itemId, 'level');

        if (this.tree.hasChildren(itemId) && this.tree.getOpenState(itemId) == -1)  //  Closed
            this.onNodeOpenStart(itemId, -1);

        if (level && level.javascript)
        {
//            console.log(level.javascript);
            var impliedChildLevel = this.getImpliedChildLevel(level);

            var fn = new Function(
                    'nodeId',
                    'impliedChildLevel',
                    'impliedChildLevelFilter',
                    level.javascript);

            this.lastImpliedChildLevelFilter = impliedChildLevel ? this.getFilter(itemId, impliedChildLevel) : null;

            fn.apply(this, [
                    itemId,
                    impliedChildLevel,
                    this.lastImpliedChildLevelFilter]);
        }
    }

    inkinru.ContentItemTreeControl.prototype.showChildrenIn = function (moduleId)
    {
        inkinru.page.getModule(moduleId).setFilter(this.lastImpliedChildLevelFilter);
    }

    inkinru.ContentItemTreeControl.prototype.onNodeOpenStart = function (id, state)
    {
        if (state == -1)    //  Closed, open now.
        {
            if (!this.tree.getUserData(id, 'toLoad'))
                return true;

            var level = this.tree.getUserData(id, 'level');

    //        if (level.children)
            {
                this.tree.setUserData(id, 'toLoad', null);
                this.loadItems(id, level.children, level);
            }

            return false;
        }

        return true;
    }

    inkinru.ContentItemTreeControl.getLevelParentList = function (level)
    {
        var arr = [];

        while (level.parent)
        {
            arr.unshift(level.parent);
            level = level.parent;
        }

        return arr;
    }

    inkinru.ContentItemTreeControl.prototype.getFilter = function (nodeId, level)
    {
        var tempNodeId;
        var parentLevels;
        var levelToSearch;
        var filter = {};

        switch (level.type)
        {
            case 'Catalog':
//                var catalog = this.catalogs[level.id];

                if (!('category' in level) || level.category == 'noFilter')
                    filter.categoryId = 'all';
                else
                {
                    parentLevels = inkinru.ContentItemTreeControl.getLevelParentList(level);
                    levelToSearch = parentLevels[level.category];
                    tempNodeId = nodeId;

                    while (tempNodeId)
                    {
                        if (this.tree.getUserData(tempNodeId, 'level') == levelToSearch)
                        {
                            filter.categoryId = this.tree.getUserData(tempNodeId, 'objectId');
                            break;
                        }

                        tempNodeId = this.tree.getParentId(tempNodeId);
                    }
                }

                if (level.related)
                {
                    for (var relatedIndex in level.related)
                    {
                        if (level.related[relatedIndex] != 'noFilter')
                        {
                            if (!parentLevels)
                                parentLevels = inkinru.ContentItemTreeControl.getLevelParentList(level);

                            levelToSearch = parentLevels[level.related[relatedIndex]];
                            tempNodeId = nodeId;

                            while (tempNodeId)
                            {
                                if (this.tree.getUserData(tempNodeId, 'level') == levelToSearch)
                                {
                                    if (!filter.related)
                                        filter.related = {};

                                    filter.related[relatedIndex] = this.tree.getUserData(tempNodeId, 'objectId');
                                    break;
                                }

                                tempNodeId = this.tree.getParentId(tempNodeId);
                            }
                        }
                    }
                }

                //  TODO:  Add filtering by custom categories.
        }

        return filter;
    }


inkinru.ContentItemTreeConfigControl = function (id)
{
    this.id         = id;
    this.nextNodeId = 0;
}

    inkinru.ContentItemTreeConfigControl.prototype.create = function (config, languages, language, sh)
    {
        var that = this;

        this.languages  = languages;
        this.language   = language;

        inkinru.page.callServerMethod('Core', 'getCategoryTrees', null, function (result) {
            if (!inkinru.page.checkAjaxResult(result))
                return;

            that.categoryTrees = mapById(result.data);

            inkinru.page.callServerMethod('Core', 'getCatalogs', {relatedInfo: true}, function (result) {
                if (!inkinru.page.checkAjaxResult(result))
                    return;

                that.catalogs = mapById(result.data);

                sh.load([
                        'type_Text',
                        'type_CategoryTree',
                        'type_Catalog',
                        'add_Text',
                        'add_CategoryTree',
                        'add_Catalog',
                        'choose',
                        'autoload',
                        'emptyMode',
                        'emptyMode_noCheck',
                        'emptyMode_disableOpen',
                        'emptyMode_hide',
                        'category',
                        'noFilter',
                        'levelProperties',
                        'implied',
                        'javascript'
                        ],
                        function (sh) {that.createWithStringsLoaded(config, sh)});
            });
        });
    }

    inkinru.ContentItemTreeConfigControl.prototype.createWithStringsLoaded = function (config, sh)
    {
        var that = this;
        var div;
        var button;

        this.sh = sh;
        this.element = document.getElementById(this.id);

        this.sortable = document.createElement('ul');

        $(this.sortable)
                .appendTo(this.element)
                .addClass('inkinru-nestedSortable');

        $(this.sortable)
                .nestedSortable({
                    forcePlaceholderSize:   true,
                    placeholder:            'inkinru-nestedSortable-placeholder',
                    tabSize:                18,
                    tolerance:              'pointer',
                    toleranceElement:       '> div',
                    items:                  'li',
                    opacity:                0.6,
                    listType:               'ul',
                    change:                 function () {that.updateAllNodeFilters()},
                    stop:                 function () {that.updateAllNodeFilters()}
                });

        if (config)
            this.addLevelsRecursive(config.tree.children);

        div = document.createElement('div');
        $(div).css({textAlign: 'right'});

        button = document.createElement('button');
        button.innerHTML = sh.get('add_Text');
        button.onclick = function () {that.addText();};
        div.appendChild(button);
        $(button).button();

        button = document.createElement('button');
        button.innerHTML = sh.get('add_CategoryTree');
        button.onclick = function () {that.addCategoryTree();};
        div.appendChild(button);
        $(button).button();

        button = document.createElement('button');
        button.innerHTML = sh.get('add_Catalog');
        button.onclick = function () {that.addCatalog();};
        div.appendChild(button);
        $(button).button();

        this.element.appendChild(div);
    }

    inkinru.ContentItemTreeConfigControl.prototype.addLevelsRecursive = function (levels, parentNode)
    {
        for (var i in levels)
        {
            var level = levels[i];
            var node = this.addLevel(level, parentNode, 'child');

            if (level.children)
                this.addLevelsRecursive(level.children, node);
        }
    }

    inkinru.ContentItemTreeConfigControl.prototype.addText = function ()
    {
        this.addLevel({type: 'Text'});
    }

    inkinru.ContentItemTreeConfigControl.prototype.addCategoryTree = function ()
    {
        this.addLevel({type: 'CategoryTree'});
    }

    inkinru.ContentItemTreeConfigControl.prototype.addCatalog = function ()
    {
        this.addLevel({type: 'Catalog'});
    }

    inkinru.ContentItemTreeConfigControl.prototype.addLevel = function (levelInfo, node, relation)
    {
        var that = this;
        var list;
        var li = document.createElement('li');
        var itemDiv;
        var div;
        var nodeId = this.getNextNodeId();
        var selected;

        itemDiv = document.createElement('div');

        $(itemDiv)
                .css({position: 'relative'})
                .appendTo(li);

        $(li).attr({id: this.id + '_' + nodeId});
        li.levelType = levelInfo.type;
        li.levelInfo = levelInfo;

        if (!node)
            this.sortable.appendChild(li);
        else
        {
            switch (relation)
            {
                case 'after':
                    node.parentNode.insertBefore(li, node.nextSibling);
                    break;
                case 'child':
                    var lists = $(node).children('ul');

                    if (lists.length)
                    {
                        lists[0].appendChild(li);
                    }
                    else
                    {
                        var newList = document.createElement('ul');
                        node.appendChild(newList);
                        newList.appendChild(li);
                    }
            }
        }

        var table = document.createElement('table');
        var thead = document.createElement('thead');
        var tbody = document.createElement('tbody');
        var tfoot = document.createElement('tfoot');
        var row, cell;
        var label;
        var span;
        var i;

        table.appendChild(thead);
        table.appendChild(tbody);
        table.appendChild(tfoot);
        itemDiv.appendChild(table);

        row = document.createElement('tr');
        tbody.appendChild(row);
        cell = document.createElement('td');
        row.appendChild(cell);


        //  Title cell

        switch (levelInfo.type)
        {
            case 'Text':
                var divId = this.id + '_' + nodeId + '_mi';

                div = document.createElement('div');
                div.setAttribute('id', divId);

                $(cell)
                        .attr({colspan: 2})
                        .append(div);

                li.textInput = new MultilingualInput(divId);
                li.textInput.create('', '500', levelInfo.text, this.languages, this.language);
                break;

            case 'CategoryTree':
            case 'Catalog':
                $(cell).css({width: '280px'});

                div = document.createElement('div');
                div.innerHTML = this.sh.get('type_' + levelInfo.type);
                $(div).css({
                    fontWeight: 'bold',
                    fontSize:   '15px'
                });

                cell.appendChild(div);
        }


        //  List cell

        switch (levelInfo.type)
        {
            case 'CategoryTree':
            case 'Catalog':
                cell = document.createElement('td');
                row.appendChild(cell);
                li.select = document.createElement('select');

                $(li.select).css({width: '280px'});
                cell.appendChild(li.select);

                switch (levelInfo.type)
                {
                    case 'CategoryTree':
                        list = this.categoryTrees;
                        break;
                    case 'Catalog':
                        list = this.catalogs;
                        break;
                    default:
                        list = [];
                }

                if (!levelInfo.id && list.length != 1)
                {
                    li.select.options[0] = new Option(
                            this.sh.get('choose'),
                            0,
                            true, true);
                }

                for (i in list)
                {
                    var item        = list[i];

                    selected = item.id == levelInfo.id;

                    li.select.options[li.select.options.length] = new Option(
                            item.title,
                            item.id,
                            selected, selected);
                }

//                if (list.length == 1)
//                {
//                    li.select.options[1].selected = true;
//                    removeZero = true;
//                }
//
//                if (removeZero && li.select.options[0].value == 0)
//                    li.select.options[0] = undefined;


                if (levelInfo.type == 'Catalog')
                {
                    row = document.createElement('tr');
                    tbody.appendChild(row);
                    cell = document.createElement('td');
                    row.appendChild(cell);
                    cell = document.createElement('td');
                    row.appendChild(cell);

                    li.filterDiv = document.createElement('div');
                    cell.appendChild(li.filterDiv);
                    this.recreateNodeFilterDiv(li, true);
                }

                li.select.onchange = function () {that.onNodeSelectChange(li, this);};
        }


        //  Category select row

        switch (levelInfo.type)
        {
            case 'CategoryTree':
                row = document.createElement('tr');
                tbody.appendChild(row);
                cell = document.createElement('td');
                row.appendChild(cell);
                li.categoryCell = document.createElement('td');
                row.appendChild(li.categoryCell);
        }

        row = document.createElement('tr');
        tbody.appendChild(row);
        cell = document.createElement('td');
        row.appendChild(cell);

        li.autoloadCheckbox = document.createElement('input');
        li.autoloadCheckbox.setAttribute('type', 'checkbox');
        li.autoloadCheckbox.checked = levelInfo.autoload;
        $(li.autoloadCheckbox).attr({id: this.id + '_autoload'});
        cell.appendChild(li.autoloadCheckbox);

        label = document.createElement('label');
        $(label).attr({'for': this.id + '_autoload'});
        label.innerHTML = this.sh.get('autoload');
        cell.appendChild(label);

        cell = document.createElement('td');
        row.appendChild(cell);
        span = document.createElement('span');
        span.innerHTML = this.sh.get('emptyMode') + ':';
        cell.appendChild(span);

        li.emptyModeSelect = document.createElement('select');
        li.emptyModeSelect.options[0] = new Option(this.sh.get('emptyMode_noCheck'), 'noCheck', levelInfo.emptyMode == 'noCheck', levelInfo.emptyMode == 'noCheck');
        li.emptyModeSelect.options[1] = new Option(this.sh.get('emptyMode_disableOpen'), 'disableOpen', levelInfo.emptyMode == 'disableOpen', levelInfo.emptyMode == 'disableOpen');
        li.emptyModeSelect.options[2] = new Option(this.sh.get('emptyMode_hide'), 'hide', levelInfo.emptyMode == 'hide', levelInfo.emptyMode == 'hide');
        cell.appendChild(li.emptyModeSelect);

        var buttonsDiv = document.createElement('div');
        var propertiesButton    = document.createElement('button');

        propertiesButton.setAttribute('type', 'button');
        propertiesButton.innerHTML = '...';
        propertiesButton.onclick = function () {that.showLevelProperties(li);};

        var a = document.createElement('a');

        $(a)
                .attr({href: 'javascript:;'})
                .appendTo(buttonsDiv);

        a.onclick = function () {that.deleteLevel(li);};

        var img = document.createElement('img');

        $(img)
                .attr({
                    border:     0,
                    src:        inkinru.page.getSystemAbsolutePath() + '/images/delete.png'
                })
                .appendTo(a);

        $(buttonsDiv)
                .css({
                    position:   'absolute',
                    top:        '2px',
                    right:      '2px'
                })
                .appendTo(itemDiv)
                .append(propertiesButton, a);

        $(propertiesButton).button();

        $(this.sortable).nestedSortable('refresh');
        return li;
    }

    inkinru.ContentItemTreeConfigControl.prototype.onNodeSelectChange = function (node, select)
    {
        if (select.value && select.options[0].value == 0)
            select.options[0] = undefined;
//console.log('onNodeSelectChange');
        switch (node.levelType)
        {
            case 'Catalog':
                this.recreateNodeFilterDiv(node, false);
                break;
            case 'CategoryTree':
                this.recreateNodeCategoryList(node);
        }
    }

    inkinru.ContentItemTreeConfigControl.prototype.recreateNodeCategoryList = function (node)
    {
//        var that = this;
        var treeId = node.select.value;

        $(node.categoryCell).html('');
        node.categorySelect = null;

        if (treeId)
        {
            inkinru.page.createCategorySelect(
                    node.categoryCell,
                    '',
                    treeId,
                    false,                      //  multiselect
                    '280px',
                    //function () {that.value = that.categorySelect.getSelectedId();},
                    null,
                    [],                         //  selectedIds
                    function (obj) {node.categorySelect = obj;});
        }
    }

    inkinru.ContentItemTreeConfigControl.prototype.recreateNodeFilterDiv = function (node, initial)
    {
        var catalogId = node.select.value - 0;

        $(node.filterDiv).html('');
        node.filterDiv.controls = {};

        if (catalogId)
        {
            var catalog = this.catalogs[node.select.value];

            var table = document.createElement('table');
            var thead = document.createElement('thead');
            var tbody = document.createElement('tbody');
            var tfoot = document.createElement('tfoot');
            var row, cell;
            var label;
            var span;
            var select;
            var input;
            var i;

            table.appendChild(thead);
            table.appendChild(tbody);
            table.appendChild(tfoot);
            node.filterDiv.appendChild(table);
//console.log(catalog);
            if (catalog.categoryMode != 'none')
            {
                row = document.createElement('tr');
                tbody.appendChild(row);
                cell = document.createElement('td');
                row.appendChild(cell);
                cell.innerHTML = this.sh.get('category') + ':';

                cell = document.createElement('td');
                row.appendChild(cell);

                select = document.createElement('select');
                node.filterDiv.controls.category = select;
                cell.appendChild(select);

                input = document.createElement('input');
                $(input).css({width: '80px', display: 'none'});
                node.filterDiv.controls.category_input = input;
                cell.appendChild(input);
            }

            for (i in catalog.relatedInfo.related)
            {
                if (catalog.relatedInfo.related[i].id)
                {
                    row = document.createElement('tr');
                    tbody.appendChild(row);
                    cell = document.createElement('td');
                    row.appendChild(cell);
                    cell.innerHTML = catalog.relatedInfo.related[i].text + ':';

                    cell = document.createElement('td');
                    row.appendChild(cell);

                    select = document.createElement('select');
                    node.filterDiv.controls['related_' + i] = select;
                    cell.appendChild(select);

                    input = document.createElement('input');
                    $(input).css({width: '80px', display: 'none'});
                    node.filterDiv.controls['related_' + i + '_input'] = input;
                    cell.appendChild(input);
                }
            }

            this.updateNodeFilters(node, initial);
        }
    }

    inkinru.ContentItemTreeConfigControl.prototype.updateNodeFilters = function (node, initial)
    {
        var parentNode;
        var oldValue;
        var info;
        var select;
        var parentIndex;
        var i, j;

        switch (node.levelType)
        {
            case 'Catalog':
                var catalog = this.catalogs[node.select.value];

                if (catalog)
                {
                    var controls = node.filterDiv.controls;
                    var parentList = this.getNodeParentList(node);
                    var filteredIndices;

                    if (controls.category)
                    {
                        filteredIndices = this.filterNodes(
                                parentList,
                                'CategoryTree',
                                'Category',
                                catalog.categoryTreeId);

                        oldValue = initial ? node.levelInfo.category : controls.category.value;
                        $(controls.category).html('');
                        controls.category.options[0] = new Option(this.sh.get('noFilter', 'noFilter', false, false));

                        for (i in filteredIndices)
                        {
                            parentIndex = filteredIndices[i] - 0;
                            parentNode = parentList[parentIndex];

                            controls.category.options[controls.category.options.length] = new Option(
                                    '(' + (parentIndex + 1) + ') ' + parentNode.select.options[parentNode.select.selectedIndex].text,
                                    parentIndex,
                                    false, false);
                        }

                        controls.category.value = oldValue;   //  Try to preserve.
                    }

                    for (i in catalog.relatedInfo.related)
                    {
                        if (catalog.relatedInfo.related[i].id)
                        {
                            info = catalog.relatedInfo.related[i];
                            select = controls['related_' + i];

                            filteredIndices = this.filterNodes(parentList, 'Catalog', info['class']);
                            oldValue = initial ? node.levelInfo.related[i] : select.value;
                            $(select).html('');
                            select.options[0] = new Option(this.sh.get('noFilter'), 'noFilter', false, false);

                            for (j in filteredIndices)
                            {
                                parentIndex = filteredIndices[j] - 0;
                                parentNode = parentList[parentIndex];

                                select.options[select.options.length] = new Option(
                                        '(' + (parentIndex + 1) + ') ' + parentNode.select.options[parentNode.select.selectedIndex].text,
                                        parentIndex,
                                        false, false);
                            }

                            select.value = oldValue;
                        }
                    }
                }
        }
    }

    inkinru.ContentItemTreeConfigControl.prototype.updateNodeFiltersRecursive = function (ul)
    {
        var that = this;

        $(ul).children('li').each(function () {
            that.updateNodeFilters(this, false);

            $(this).children('ul').each(function () {
                that.updateNodeFiltersRecursive(this);
            })
        });
    }

    inkinru.ContentItemTreeConfigControl.prototype.updateAllNodeFilters = function ()
    {
        this.updateNodeFiltersRecursive(this.sortable);
    }

    inkinru.ContentItemTreeConfigControl.prototype.deleteLevel = function (node)
    {
        node.parentNode.removeChild(node);
        $(this.sortable).nestedSortable('refresh');
    }

    inkinru.ContentItemTreeConfigControl.prototype.showLevelProperties = function (node)
    {
        var that = this;

        if (!node.propertiesDialog)
        {
            node.propertiesDialog = document.createElement('div');

            var table = document.createElement('table');
            var thead = document.createElement('thead');
            var tbody = document.createElement('tbody');
            var tfoot = document.createElement('tfoot');
            var row, cell;
            var label;
            var span;
            var id;
            var i;

            table.appendChild(thead);
            table.appendChild(tbody);
            table.appendChild(tfoot);
            node.propertiesDialog.appendChild(table);

            row = document.createElement('tr');
            tbody.appendChild(row);
            cell = document.createElement('td');
            row.appendChild(cell);
            node.propertiesDialog.impliedCheckbox = document.createElement('input');
            node.propertiesDialog.impliedCheckbox.setAttribute('type', 'checkbox')

            id = this.id + node.id;

            $(node.propertiesDialog.impliedCheckbox).attr({id: id});

            label = document.createElement('label');
            label.innerHTML = this.sh.get('implied');
            $(label).attr({'for': id});
            $(cell).append(node.propertiesDialog.impliedCheckbox, label);

            row = document.createElement('tr');
            tbody.appendChild(row);
            cell = document.createElement('td');
            row.appendChild(cell);
            cell.innerHTML = this.sh.get('javascript') + ':';

            row = document.createElement('tr');
            tbody.appendChild(row);
            cell = document.createElement('td');
            row.appendChild(cell);
            node.propertiesDialog.javascriptTextarea = document.createElement('textarea');
            cell.appendChild(node.propertiesDialog.javascriptTextarea)

            $(node.propertiesDialog.javascriptTextarea).css({
                    width:  '570px',
                    height: '100px'
            });

            $(node.propertiesDialog).dialog({
                    bgiframe:   true,
                    modal:      true,
                    autoOpen:   false,
                    width:      600,
                    title:      this.sh.get('levelProperties'),
                    buttons:    {OK: function () {that.onLevelPropertiesOk(node);}}
            });
        }

        node.propertiesDialog.impliedCheckbox.checked = node.levelInfo.implied;
        node.propertiesDialog.javascriptTextarea.value = node.levelInfo.javascript ? node.levelInfo.javascript : '';

        $(node.propertiesDialog).dialog('open');
    }

    inkinru.ContentItemTreeConfigControl.prototype.onLevelPropertiesOk = function (node)
    {
        node.levelInfo.implied      = node.propertiesDialog.impliedCheckbox.checked;
        node.levelInfo.javascript   = node.propertiesDialog.javascriptTextarea.value;
        $(node.propertiesDialog).dialog('close');
    }

    inkinru.ContentItemTreeConfigControl.prototype.getParentNode = function (node)
    {
        node = node.parentNode.parentNode;

        return node.tagName.toLowerCase() == 'li' ? node : null;
    }

    inkinru.ContentItemTreeConfigControl.prototype.getNodeParentList = function (node)
    {
        var arr = [];

        while (true)
        {
            var parent = this.getParentNode(node);

            if (!parent)
                break;

            arr.unshift(parent);
            node = parent;
        }

        return arr;
    }

    inkinru.ContentItemTreeConfigControl.prototype.filterNodes = function (arr, type, className, id)
    {
        //var result = [];
        var indices = [];

nodes:
        for (var i in arr)
        {
            var node = arr[i];

            if (node.levelType != type)
                continue nodes;

            var obj;

            if (className)
            {
                switch (type)
                {
                    case 'CategoryTree':
                        obj = this.categoryTrees[node.select.value];

                        if (typeof(id) != 'undefined' && obj.id != id)
                            continue nodes;

                        if ((obj.itemClass != className) && !(className == 'Category' && !obj.itemClass))
                            continue nodes;

                        break;

                    case 'Catalog':
                        obj = this.catalogs[node.select.value];

                        if (obj.itemClass != className)
                            continue nodes;
                }
            }

            //result.push(node);
            indices.push(i);
        }

        //return result;
        return indices;
    }

    inkinru.ContentItemTreeConfigControl.prototype.getNextNodeId = function ()
    {
        return 'new' + this.nextNodeId++;
    }

    inkinru.ContentItemTreeConfigControl.prototype.nodeToLevelInfo = function (node)
    {
        var i;

//        var levelInfo = {
//            type:   node.levelType
//        };
        var levelInfo = jQuery.extend({}, node.levelInfo);

        delete levelInfo.children;

        levelInfo.autoload  = node.autoloadCheckbox.checked;
        levelInfo.emptyMode = node.emptyModeSelect.value;

        switch (levelInfo.type)
        {
            case 'Text':
                levelInfo.text = node.textInput.getValues();
                break;
            case 'CategoryTree':
            case 'Catalog':
                levelInfo.id        = node.select.value - 0;
        }

        switch (levelInfo.type)
        {
            case 'Catalog':
                var catalog = this.catalogs[levelInfo.id];

                if (catalog.categoryMode != 'none')
                {
                    if (!isNaN(parseInt(node.filterDiv.controls.category.value)))
                        levelInfo.category = node.filterDiv.controls.category.value - 0;
                    else
                        levelInfo.category = node.filterDiv.controls.category.value;
                }

//                levelInfo.category = catalog.categoryMode == 'none' ? 0 : node.filterDiv.controls.category.value - 0;
                levelInfo.related = [];

                for (i in catalog.relatedInfo.related)
                {
                    if (!catalog.relatedInfo.related[i].id)
                        levelInfo.related.push('noFilter');
                    else
                    {
    //                    var v;
                        var optionValue = node.filterDiv.controls['related_' + i].value;

    //                    if (!isNaN(parseInt(optionValue)))
    //                        v = optionValue - 0;
    //                    else
    //                        v = optionValue;

                        levelInfo.related.push(isNaN(parseInt(optionValue)) ? optionValue : optionValue - 0);
    //                    levelInfo.related.push(node.filterDiv.controls['related_' + i].value);
                    }
                }
        }
//console.log(levelInfo);
        return levelInfo;
    }

    inkinru.ContentItemTreeConfigControl.prototype.getConfig = function ()
    {
        var levelsById = {};
        var arr = $(this.sortable).nestedSortable('toArray', {expression: new RegExp('^(' + this.id + ')_(.*)$')});
        var item;
        var parent;
        var root;
        var node;
        var level;
        var i;

        for (i in arr)
        {
            item = arr[i];

            if (item.item_id == 'root')
                root = level = {};
            else
            {
                node = document.getElementById(this.id + '_' + item.item_id);
                level = this.nodeToLevelInfo(node);
            }

            levelsById[item.item_id] = level;
        }

        for (i in arr)
        {
            item = arr[i];

            if (item.parent_id != 'none')
            {
                parent = levelsById[item.parent_id];

                if (parent.children)
                    parent.children.push(levelsById[item.item_id]);
                else
                    parent.children = [levelsById[item.item_id]];
            }
        }

        return {tree: root};
    }

