/*
Script: RIA DHTML Tree 0.8.2
	Class for make simple DHTML Tree.
	http://linux.ria.ua/rdTree/
	http://vkurseweba.ru/blog/rdtree
Date:
	13 September 2009

Browser Compatibility:
	Safari 2+, Internet Explorer 6+, Firefox 2+ (and browsers based on gecko), Opera 9+.

License:
	LGPL

Author:
	Oleg Cherniy <oleg.cherniy(at)gmail(dot)com>
	Alexander Bekbulatov <info(at)vkurseweba(dot)ru>
*/

var rdTree = new Class({

    Implements: Options,

    options: {							// options
        img: {
            path: 'img/rdTree/firebug/',
            itemName: '',
            plusName: 'plus.gif',
            minusName: 'minus.gif',
            loaderName: 'loader.gif'	// ajax loader image
        },
        classes: {
            selected: 'selected',
            opened: 'opened',
            first: 'first',
            last: 'last',
            center: 'center',
            centerNode: 'centerNode',
            lastNode: 'lastNode'
        },
        links : {
            host: '/',					// host
            getNode : 'data.json?'		// path to json data
        },
        openSelectedNode: true,
        loadableAnchors: false
    },

    initialize: function(id, options){
        this.id = id;
        this.setOptions(options);
        this.makeLinkForLiText( $(this.id) );	// pass root node
        this.makeSelected();
        this.make( $(this.id) );				// pass root node
        this.initDelegate();
    },

    initDelegate: function(){

        var this_event = this;
        $(this.id).addEvent('click:relay(a)', function(){
            this_event.changeSelected(this, false);
        })

    },
    openParentForSelectedLink: function(link){
        var li = link.getParent('li');
        var ul = li.getParent();
        if (ul != $(this.id)) {
            var liParent = ul.getParent();
            ul.addClass(this.options.classes.opened);
            /*
			if (li.getParent().getLast() == li) {						// some bug fix
				li.getElement('ul').setStyle('background', 'none');
			}
			*/
            this.openParentForSelectedLink(liParent.getElement('a'));
        }
    },

	// проходим по всему дереву и заменяем текст на ссылку
    makeLinkForLiText: function(ul) {
        var menus = ul.getElements('li');
        var this_cycle = this;
        menus.each(function(li, i){
            var link;
            if (li.firstChild.nodeType != 1) {
                var text = li.firstChild.nodeValue;
                link = new Element('a');
                link.set('text',text);
                link.replaces(li.firstChild);
            } else {
                link = li.getElement('a');
            }
            this_cycle.divWrapper(link);
        });
    },

    tableWrapper: function(link) {
        var table = new Element('table');
        table.inject(link, 'before');
        var tbody = new Element('tbody');
        tbody.inject(table);
        var table_row = new Element('tr');
        table_row.inject(tbody);
        var icon_container = new Element('td', {
            'class': 'icon'
        } );
        icon_container.inject(table_row);
        var link_container = new Element('td');
        link_container.inject(table_row);
        link.inject(link_container);
    },

    divWrapper: function(link) {
//       $jq(link).wrap('<div class="icon" />');
    },

    getSelected: function() {
        return $(this.id).getElement('a.'+this.options.classes.selected);
    },

    makeSelected: function() {
        var selectedLink = this.getSelected();
        if ($chk(selectedLink)) {
            this.openParentForSelectedLink(selectedLink);
        }
    },

    changeSelected: function(link, expand) {
        var selectedLink = this.getSelected();
        if ($chk(selectedLink)) {
            selectedLink.removeProperty('class');
        }
        link.setProperty('class', this.options.classes.selected);
        if (expand && this.options.openSelectedNode && link.get('rel') == 'loadable') {			// if node is loadable you can expand it
            var ul = link.getParent('li').getElement('ul');
            if ($chk(ul)) {
                this.expandNode(ul,ul.getParent().getElement('img'));
            }
        }


    },

    make: function(ul){
        var menus = ul.getElements('li');
        var options = this.options;
        var this_cycle = this;
        menus.each(function(li, i){
            var link = li.getElement('a');
            //var img = new Element('img');
            var ul = li.getElement('ul');

//            if (li.getParent().getLast() == li)  {
//                li.setProperty('class', options.classes.last);
//            } else {
                li.setProperty('class', options.classes.center);
//            }

            if ($chk(ul) || link.get('rel') == 'loadable') {		// add node to parent
                this_cycle.applyNode(li,link);
            } else {
                this_cycle.applyItem(li,link);
            }

        // Change link setup
        //link.addEvent('click', function(){			// not necessary function
        //    this_cycle.changeSelected(link, false);
        //});

        });
    },

    getNode: function(li, link) {						// get node from json

        var this_event = this;
        var options = this.options;

        var id = link.get('id').replace(/\D+/, '');	// attribute contains item id, get it
        var parentLink = link.get('href').replace(new RegExp(options.links.host), '');
        var img = li.getElement('img');

        var clickable = (options.loadableAnchors) ? $$(img, link) : img;

        new Request.JSON({

            url: options.links.host + options.links.getNode + id + '/' + parentLink,
            method: 'get',
            onRequest: function() {
                clickable.removeEvents('click');
                img.set('src', options.img.path + options.img.loaderName);
            },
            onComplete: function() {
                img.set('src', options.img.path + options.img.minusName);
            },
            onSuccess: function(jsonObj) {

                // form ul list from json data

                ul = new Element('ul', {
                    'class' : options.classes.opened
                }).inject(li);

                jsonObj.list.each(function(el) {
                    var li = new Element('li').inject(ul);
                    new Element('a', {
                        'href' : (el.link.substr(0,1) == '#' ? '' : options.links.host) + el.link,
                        'id' : el.id,
                        'text' : el.name,
                        'rel' : (el.loadable + 0 > 0) ? 'loadable' : 'non-loadable'
                    }).inject(li);
                });

                this_event.makeLinkForLiText(ul);	// wrap new items with table
                this_event.make(ul);

//                if ( li.getParent().getLast() == li) {
//                    ul.setStyle('background', 'none');
//                }

                clickable.addEvent('click', function(event){
                    event.preventDefault();
                    this_event.toggleNode(li.getElement('ul'),img);		// new node can toggle children
                    this_event.changeSelected(link, false);
                });



            }
        }).send();

    },


	// добавляем ветку в дерево
    applyNode: function(li,link){
//		console.info('brunch: '+link);
        var img = new Element('img');
//        var td = link.getParent().getParent().firstChild;
        var imgSrc;
        var options = this.options;
        var this_event = this;

        var ul = li.getElement('ul');

        if ($chk(ul) && ul.getStyle('display') == 'block') {
            imgSrc = this.options.img.minusName;
        } else {
            imgSrc = this.options.img.plusName;
        }

//        img.setProperties({
//            'src': this.options.img.path + imgSrc,
//			'class':'bullet',
//			'style':'cursor:pointer;'
//        });
		
		$jq(li).prepend($jq(img).attr({
            'src': this.options.img.path + imgSrc,
			'class':'bullet',
			'style':'cursor:pointer;'
        }));

/*        if ($chk(ul) && li.getParent().getLast() == li) {
            ul.setStyle('background', 'none');
        }
*/
        var clickable = (options.loadableAnchors) ? $$(img, link) : img

        clickable.addEvent('click', function(event){
            event.preventDefault();
            if ($chk(ul)) {
                this_event.toggleNode(ul,img);
            }
            else {
                this_event.getNode(li, link);	// if node has not ul-child node will upload it
            }
        });

//        if (li.getParent().getLast() == li) {
//            li.setProperty('class', this.options.classes.lastNode);
//        } else {
            li.setProperty('class', this.options.classes.centerNode);
//        }
    },

	// добавляем лист в дерево
    applyItem: function(li,link){
//		console.info('leaf: '+link);
        if (this.options.img.itemName != '') {
            var img = new Element('img');
//            var td = link.getParent().getParent().firstChild;
//            img.inject(td).setProperties({
//                'src': this.options.img.path + this.options.img.itemName
//            });
			$jq(li).prepend($jq(img).attr({
				'src': this.options.img.path + this.options.img.itemName,
				'class':'bullet'
			}));

        }
    },

    /* ----------------------------------------- */
    // Service methods
    toggleNode: function(ul,img) {
        if (ul.hasClass(this.options.classes.opened)) {
            this.collapseNode(ul,img);
        } else {
            this.expandNode(ul,img);
        }
    },

    expandNode: function(ul,img) {
        ul.setProperty('class', this.options.classes.opened);
        img.setProperties({
            'src': this.options.img.path + this.options.img.minusName
        });
    },

    collapseNode: function(ul,img) {
        ul.removeProperty('class');
        img.setProperties({
            'src': this.options.img.path + this.options.img.plusName
        });
    },

    expandAll: function(id) {
        var root;
        if (id != null) {
            root = $(id).getParent('li');
        } else {
            root = $(this.id);
        }
        var uls = root.getElements('ul');
        var this_cycle = this;
        uls.each(function(ul, i){
            if (!(ul.hasClass(this_cycle.options.classes.opened))) {
                this_cycle.expandNode(ul,ul.getParent().getElement('img'));
            }
        });
    },

    collapseAll: function(id) {
        var root;
        if (id != null) {
            root = $(id).getParent('li');
        } else {
            root = $(this.id);
        }
        var uls = root.getElements('ul');
        var this_cycle = this;
        uls.each(function(ul, i){
            if (ul.hasClass(this_cycle.options.classes.opened)) {
                this_cycle.collapseNode(ul,ul.getParent().getElement('img'));
            }
        });
    },

    checkSelectedVisible: function(ul) {
        if (ul != $(this.id)) {
            if (!(ul.hasClass(this.options.classes.opened))) {
                this.expandNode(ul,ul.getParent().getElement('img'));
                this.checkSelectedVisible(ul.getParent('ul'));
            }
        }
    },

    select: function(id) {
        this.checkSelectedVisible($(id).getParent('ul'));
        this.changeSelected($(id), true);
    },

    getChildren: function(node) {

        var table = $$(node.getParent('li').getChildren('ul').getChildren('li')).getChildren('table');
        var links = $$(table).getElements('a');

        var chindren = [];
        links.each(function(el) {
            chindren.push(
                $H({
                    id: el.get('id'),
                    href: el.get('href'),
                    text: el.get('text')
                })
                );
        })

        return chindren;
    },

    addNode: function(node, where) {

        var parentLi = where.getParent('li');
        var parentImg = where.getParent().getParent().getElement('img');
        var ul = parentLi.getElement('ul');

        if (!$chk(ul)) {
            ul = new Element('ul').inject(parentLi);
        }
        else {
            ul.getElements('li').addClass(this.options.classes.center);
        }


        li = new Element('li', {
            'class' : this.options.classes.last
        }).inject(ul);
        var a = new Element('a', node).inject(li);
        this.tableWrapper(a);

        var td = li.getElement('td.icon');
        var img = new Element('img', {
            'src': this.options.img.path + this.options.img.itemName
        }).inject(td);
        this.expandNode(ul, parentImg);
    },

    remove: function(node) {

        var parentLi = node.getParent('li');
        var ul = parentLi.getParent('ul');

        parentLi.dispose();

        if ($chk(ul.getElement('li'))) return;

        ul.getParent().getElement('img').set('src', this.options.img.path + this.options.img.itemName);
        ul.dispose();

    }

});

