/** CATEGORY TREE FOR IGALLERY COMPONENT **/

categoryTreeClass = new Class ({
    options: {                  //--> set optional options
        listWidth: 200,         //--> may be 'auto'
        containerWidth: 400,    //--> 0 equals 'auto'
        containerHeight: 200,   //--> may be 'auto'
        velocity: 1,            //--> velocity mouseover navigation runs at
        area: 25,               //--> contact area for mouseover navigation both horizontally and vertically
        view: 1,                //--> 1 = categoryTree view, 0 = gallery view, for path highlighting
        containerId: 'iGalleryCatTreeContainer',
        wrapperId: 'iGalleryCatTreeWrapper',
        levelId: 'iGalleryCatTreeLevel',
        listId: 'iGalleryCatTreeList',
        columnClass: 'iGalleryColumn',
        levelClass: 'iGalleryLevel'
    },
    initialize: function(id,options) {  //--> run application setup
        this.setOptions(options);
        this.requestArray = new Array(), this.sourceArray = new Array(),
        this.container = $(this.options.containerId);
        this.wrapper = $(this.options.wrapperId);
        this.container.setStyle('height',this.options.containerHeight);
        this.container.setStyle('width',this.options.containerWidth);
        this.lists = $$('#' + this.options.wrapperId + ' li');
        $('iGalleryCatTreeArrowLeftDiv').setStyle('height',this.options.containerHeight);
        $('iGalleryCatTreeArrowRightDiv').setStyle('height',this.options.containerHeight);
        $('iGalleryCatTreeArrowBottomDiv').setStyle('width',this.options.containerWidth);
        $('iGalleryCatTreeArrowTopDiv').setStyle('width',this.options.containerWidth);
        this.parseLevels();
        this.setEffects();
        this.setNavigation();
        this.requestTree(id);
    },
    parseLevels: function() {    //--> collect and store list/tree information as application source
        this.lists.each(function(el,i) {
            var nel = el.clone(), last = nel.getLast(), lid = el.id.split('-');
            (last.getTag() == 'ul') ? last.remove() : false;
            this.sourceArray[lid[1]] = new Array();
            this.sourceArray[lid[1]].id = lid[1];
            this.sourceArray[lid[1]].parent = el.getParent().getParent().id;
            this.sourceArray[lid[1]].type = ($$('#' + el.id + ' ul') != '') ? 'category' : 'gallery';
            this.sourceArray[lid[1]].child = (this.sourceArray[lid[1]].type == 'category') ? last.getChildren() : false;
            this.sourceArray[lid[1]].siblings = el.getParent().getChildren();
            this.sourceArray[lid[1]].html = nel.innerHTML;
        },this);
    },
    setEffects: function() {    //--> setup effects used by the application
        this.scroller = new Fx.Scroll(this.options.containerId, { wait: false, duration: 600, transition: Fx.Transitions.linear });
    },
    setNavigation: function() { //--> setup container navigation events
        this.treeScroll = new newScroller(this.options.containerId, { area: this.options.area, velocity: this.options.velocity });
	    this.container.addEvent('mouseenter',this.treeScroll.start.bind(this.treeScroll));
        this.container.addEvent('mouseleave',this.treeScroll.stop.bind(this.treeScroll));
    },
    requestTree: function(id) { //--> run application
        this.totalSize = 0;
        this.requestArray.each(function(item,i) { item.remove(); },this);
        this.requestArray = new Array();
        this.wrapper.empty();
        this.startId = (this.sourceArray[id].child && this.options.view != 1) ? this.sourceArray[id].child[0].id.split('-')[1] : id;
        this.buildTree(this.startId);
        this.displayTree();
        this.options.view = 0;
    },
    buildTree: function(id) {    //--> build and store requested tree structure
        this.levelEL = new Array(), this.levelID = this.options.levelId;
        this.sourceArray[id].siblings.each(function(el,i) {
            var eId = el.id.split('-')[1], eHtml = this.sourceArray[eId].html, eType = this.sourceArray[eId].type;
            var eClass = (eId == id && id != this.startId && this.options.view != 1) ? 'active' : 'passive';
            this.levelID = this.levelID.concat('-' + this.sourceArray[eId].id);
            this.levelEL.push(this.buildListItem(eHtml,eId,eClass,eType));
        },this);
        var newElement = this.buildLevel(this.levelEL,this.levelID);
        this.requestArray.unshift(newElement);
        if(this.sourceArray[id].parent != this.options.wrapperId) { this.buildTree(this.sourceArray[id].parent.split('-')[1]); }
    },
    buildLevel: function(html,id) { //--> builds tree level elements
        var divLevel = new Element('div', { 'id': id, 'class': this.options.columnClass, 'styles': { 'height': this.options.containerHeight, 'width': this.options.listWidth } });
        var listLevel = new Element('ul', { 'class': this.options.levelClass });
        html.each(function(el,i) { el.injectInside(listLevel) },this);
        listLevel.injectInside(divLevel);
        return divLevel;
    },
    buildListItem: function(html,id,cl,type) {  //--> builds category/gallery elements in tree level
        var listItem = new Element('li', { 'id': this.options.listId + '-' + id, 'class': cl });
        listItem.setHTML(html);
        if(type == 'category') { listItem.setStyle('cursor','pointer'); listItem.addEvent('click',this.requestTree.bind(this,id)); }
        return listItem;
    },
    displayTree: function() {   //--> compiles created elements and inserts them into the main container
        var containerSize = this.container.getSize();
        this.requestArray.each(function(item,i) {
            item.injectInside(this.wrapper);
            var itemScroll = new newScroller(item.id, { area: this.options.area, velocity: this.options.velocity });
            item.addEvent('mouseenter',itemScroll.start.bind(itemScroll));
            item.addEvent('mouseleave',itemScroll.stop.bind(itemScroll));
            this.totalSize = this.totalSize + item.getSize().size.x;
        },this);
        this.wrapper.setStyle('width',this.totalSize);
        var newSize = this.container.getSize();
        var x = (newSize.scrollSize.x > containerSize.size.x) ? newSize.scrollSize.x - containerSize.size.x : 0;
        this.scroller.scrollTo(x,0);
    }
});

categoryTreeClass.implement(new Options, new Events);

newScroller = new Class({
	options: {
		area: 50,
		velocity: 1
	},
	initialize: function(element,options){
		this.setOptions(options);
		this.element = $(element);
		this.listener = ($type(this.element) != 'element') ? $(this.element.getDocument().body) : this.element;
		this.timer = null;
		this.coord = this.getCoords.bindWithEvent(this);
		this.arrowTop = $('iGalleryCatTreeArrowTopImg');
        this.arrowLeft = $('iGalleryCatTreeArrowLeftImg');
        this.arrowRight = $('iGalleryCatTreeArrowRightImg');
        this.arrowBottom = $('iGalleryCatTreeArrowBottomImg');
	},
	start: function(){
		this.listener.addEvent('mousemove',this.coord);
	},
	stop: function(){
		this.listener.removeEvent('mousemove',this.coord);
		this.timer = $clear(this.timer);
		this.arrowTop.setStyle('display','none');
		this.arrowLeft.setStyle('display','none');
		this.arrowRight.setStyle('display','none');
		this.arrowBottom.setStyle('display','none');
	},
	getCoords: function(event){
		this.page = (this.listener.getTag() == 'body') ? event.client : event.page;
		if(!this.timer) this.timer = this.scroll.periodical(50, this);
	},
	scroll: function(){
	    var size = this.element.getSize();
        var pos = this.element.getPosition();
        var wSize = $('iGalleryCatTreeWrapper').getSize();
        var cSize = $('iGalleryCatTreeContainer').getSize();
        var wPos = $('iGalleryCatTreeWrapper').getPosition();
        var child = this.element.getFirst();
        var childSize = child.getSize();
        var change = {'x': 0, 'y': 0};
        var childCenterX = (size.size.x/2).round() - 8 - (wPos.x - pos.x + cSize.scroll.x);
        var childCenterY = (size.size.y/2).round() - 8;
        if((this.element.id != 'iGalleryCatTreeContainer' || this.element.id != 'iGalleryCatTreeWrapper') && (childSize.size.y > size.size.y || childSize.size.x > wSize.size.x) && childCenterX >= 0) {
            if(size.scrollSize.y - size.scroll.y <= size.size.y) {
                this.arrowTop.setStyle('display','block');
                this.arrowTop.setStyle('left',childCenterX);
                this.arrowBottom.setStyle('display','none');
            } else if(size.scroll.y == 0) {
                this.arrowBottom.setStyle('display','block');
                this.arrowBottom.setStyle('left',childCenterX);
                this.arrowTop.setStyle('display','none');
            } else {
                this.arrowTop.setStyle('display','block');
                this.arrowTop.setStyle('left',childCenterX);
                this.arrowBottom.setStyle('display','block');
                this.arrowBottom.setStyle('left',childCenterX);
            }
        } else if(childSize.size.x > size.size.x) {
            if(size.scrollSize.x - size.scroll.x <= size.size.x) {
                this.arrowLeft.setStyle('display','block');
                this.arrowLeft.setStyle('top',childCenterY);
                this.arrowRight.setStyle('display','none');
            } else if(size.scroll.x == 0) {
                this.arrowRight.setStyle('display','block');
                this.arrowRight.setStyle('top',childCenterY);
                this.arrowLeft.setStyle('display','none');
            } else {
                this.arrowLeft.setStyle('display','block');
                this.arrowLeft.setStyle('top',childCenterY);
                this.arrowRight.setStyle('display','block');
                this.arrowRight.setStyle('top',childCenterY);
            }
        }
        for (var z in this.page){
            if(this.page[z] < (this.options.area + pos[z]) && size.scroll[z] != 0) {
                change[z] = (this.page[z] - this.options.area - pos[z]) * this.options.velocity;
            } else if(((this.page[z] + this.options.area) > (size.size[z] + pos[z])) && ((size.scroll[z] + size.size[z]) != size.scrollSize[z])) {
                change[z] = (this.page[z] - size.size[z] + this.options.area - pos[z]) * this.options.velocity;
            }
        }
        if(change.y || change.x) { this.element.scrollTo(size.scroll.x + change.x, size.scroll.y + change.y); }
	}
});
newScroller.implement(new Options, new Events);
