/**
 * @author VasiliyK
 */
 
 /*
    Contructor for panel element
    
    *id - element ID
    *text - element text
 */
PanelElement = function(id, text, imgUrl)
{
    this.Id = id;
    this.Text = text;
    this.imgUrl = imgUrl;
}

var orientations = {
    horizontal : 0,
    vertical : 1
}
 
/*
    Constructor for Sliding panel (panel have absolute position, so it have to be placed in another element with absolute position)
    
    *initTop - initial top value
    *initLeft - initial left value
    *elements - elements array (see - PanelElement constructor)
    *idPrefix - prefix for elements ids
    *selectedChangedCallback - callback calls when selected element changes
    *elementSize - width of the element
*/
SlidingPanel = function(initTop, initLeft, elements, idPrefix, selectedChangedCallback, 
                        elementSize, orientation, alwaysSlide, visibleSize, cssClassName, delay, hideElements, visibleNum, hideNum)
{
	this.maxCategoryNameLength = 17;
    this.visibleNum = 100;
    this.hideNum = hideNum || 1;
    this.delay = delay || 0;
    this.isDataLoaded = false;
    this.maxWidth = 960;
    this.initLeft = initLeft;
    this.initTop = initTop;
    this.orientation = orientation;
    this.idPrefix = idPrefix || "Element";
    this.cssClassName = cssClassName || "slidingElement";
    
    elementSize = elementSize || 250;
    orientation = orientation || orientations.horizontal;
    if (typeof(alwaysSlide) == "undefined")
    {
        alwaysSlide = true;
    }    
    
    if (!alwaysSlide && arguments.length < 9)
    {
        throw "When alwaysSlide == false, visibleSize cant't be undefined";
    }
    
    if (typeof(hideElements) == "undefined")
    {
        this.hideElements = false;
    } 
    else
    {
        this.hideElements = true;
    } 
        
    if (this.hideElements && arguments.length < 13)
    {
        throw "When hideElements == true, visibleNum cant't be undefined";
    }
    
    if (this.hideElements)
    {
        this.visibleNum = visibleNum;
    }
    
    /*
        Sets sliding panel top
        
        *top - top in px
    */
    this.setTop = function(top)
    {
        $(this.panel).css('top', top.toString()+"px");
    }
    
    /*
        Sets sliding panel left
        
        *left - left in px
    */
    this.setLeft = function(left)
    {
        $(this.panel).css('left', left.toString()+"px");
    }
    
	var orientClass = this.orientation == orientations.horizontal ? "horizontal" : "vertical";
    this.panel = $("<div></div>");
    $(this.panel).css({
        'top' : initTop.toString()+"px",
        'left' : initLeft.toString()+"px",
        'position' : 'absolute'
    }).addClass(orientClass);
    
    this.loadData = function (elements, saveFocus)
    {
        this.isDataLoaded = false;
        $(this.panel).empty();
        this.elements = [];
        var tmpHtml = "";

        for (var i = 0; i < elements.length; i++)
        {
            var elementStyle = "";
            if (this.orientation == orientations.horizontal)
            {
                elementStyle = "left:"+(i*elementSize).toString()+"px;width:"+elementSize+"px;height:40px;";
            }
            else
            {
                elementStyle = "top:"+(i*elementSize).toString()+"px;width:280px;height:"+elementSize+"px;";
            }
            
            var tmpId = "div"+this.idPrefix+elements[i].Id;
            this.elements[i] = "#"+tmpId;
            var element= "";
            element += "<div id='"+tmpId+"' class='"+this.cssClassName;
            element += (this.orientation == orientations.horizontal) ? " inactive": "";
            
            var elementContent = elements[i].Text;
            element += (elementContent.indexOf(">") == (elementContent.length - 1)) ? " folder" : "";
            elementContent = elementContent.replace(">","");
			if (this.orientation == orientations.vertical) {
				elementContent = elementContent.length > this.maxCategoryNameLength ? elementContent.substring(0, this.maxCategoryNameLength) + "..." : elementContent;
			}
            
            element += "' style='"+elementStyle+"'><div class='bracketLeft' />";
            if (typeof(elements[i].imgUrl) != "undefined" && elements[i].imgUrl != "")
            {
                var imgId = "img"+this.idPrefix+elements[i].Id;
                var imageHtml = "<img title='"+elements[i].imgUrl+"' id='"+imgId+"' width='32' height='32' class='slidingPanelImage' />"
				elementContent = "<div class='channelLogo'>" + imageHtml + "</div><div style='display:inline'>" + elementContent + "</div>";
            }
            element += elementContent;
            element += (element.indexOf("folder") != - 1) && (this.orientation != orientations.horizontal) ? "<div class='bracketRight folderImg' /></div>" : "<div class='bracketRight' /></div>";
            tmpHtml += element;

        }
        $(this.panel).html(tmpHtml);
		
		if (!saveFocus || this.index < 0) {
			this.index = 0;
		}
		
        this.focusElement(this.index);
        this.blurPanel();
		
		this.slideToInit(true);
        this.isDataLoaded = true;
        tmpHtml = null;
    }
    
    this.unload = function () {
        $(this.panel).remove();
        this.panel = null;
        this.elements.length = 0;
        this.elements = null;
        this.isDataLoaded = false;
        this.maxWidth = null;
        this.initLeft = null;
        this.initTop = null;
        this.orientation = null;
        this.idPrefix = null;
        this.cssClassName = null;
    }
    
    /*
        Focuses element in panel with selected element
        
        *index - index of the element to focus
    */
    this.focusElement = function (index) {
        var element = $(this.elements[index], this.panel);
        
		element.addClass("focused");
        if (this.orientation == orientations.horizontal) {
			var forEnd = (index + 3) > this.elements.length ? this.elements.length : index + 3;
			
			for (var i = index; i < forEnd; i++) {
				var name = this.elements[i].replace("div", "img");
				
				if (($(name).attr("src") == "") || (typeof($(name).attr("src")) == "undefined")) {
					$(name).attr("src", $(name).attr("title"));
				}
			}
        } else {
			if ($(element).hasClass("folder")) {
				$(this.elements[index] + " > .bracketRight").addClass("folderImgW");
				$(this.elements[index] + " > .bracketRight").removeClass("folderImg");
			}
        }   
        
        if (index != this.index) {
            var spacing = 0;
            
            if (alwaysSlide) {
                if (this.orientation == orientations.horizontal) {
                    spacing = this.initLeft - parseInt(element.css('left'));
                } else {
                    spacing = this.initTop - parseInt(element.css('top'));
                }
            } else {
                var relativeSpacing = 0;
                var space = 0;
                if (this.orientation == orientations.horizontal) {
                    relativeSpacing = parseInt(element.css('left')) + parseInt($(this.panel).css('left'));
                    space = parseInt(element.css('left'));
                    spacing = parseInt($(this.panel).css('left'));
                }
                else {
                    relativeSpacing = parseInt(element.css('top')) + parseInt($(this.panel).css('top'));
                    space = parseInt(element.css('top'));
                    spacing = parseInt($(this.panel).css('top'));
                }
                
                if (relativeSpacing + elementSize > visibleSize) {
                    spacing = visibleSize - space - elementSize;
                } else if (relativeSpacing < 0) {
                    spacing = -space;
                }
            }
            
            this.index = index;
            this.slide(spacing);
            if (this.isDataLoaded) {
                Logger.write("======Selected changed!"+this.elements.toSource(), "SlidingPanel");
                
                this.invokeSelectedChangedCallback();
            }
        }
    }
	
	/*
        Blurs element in panel with selected element
        
        *index - index of the element to blur
    */
    this.blurElement = function (index) {
        Logger.write("=====Bluring element: "+this.elements[index], "SlidingPanel");
        var element = $(this.elements[index], this.panel);
		element.removeClass("focused");
        if (this.orientation == orientations.horizontal) {
			var name = this.elements[index].replace("div","img");
			$(name).attr("src", "");
        } else {
			if($(element).hasClass("folder")) {
				$(this.elements[index] + " > .bracketRight").addClass("folderImg");
				$(this.elements[index] + " > .bracketRight").removeClass("folderImgW");
			}
        }
		if (this.hideElements) {
			element.hide();
		}
    }
    
    this.invokeSelectedChangedCallback = function()
    {
        var cb = function (self) {
			self.runCallback(self);
		}
		
        var self = this;
        
        if (typeof(this.selectedChangedTimeout) != "undefined")
        {
			clearTimeout(this.selectedChangedTimeout);
        }
        
        (this.delay > 0) ? this.selectedChangedTimeout = setTimeout(function(){cb(self);}, this.delay) : cb(self);          
    }
	
	this.stopTimer = function () {
		if (this.selectedChangedTimeout) {
			clearTimeout(this.selectedChangedTimeout);
		}
	}
    
    this.runCallback = function (self) {
        selectedChangedCallback(self.elements[self.index], self.index);
    }
    /*
        Slides panel to new position
        
        *newPosition - new position of the panel (left or top, relative to orientation)
    */
    this.slide = function (newPosition, withoutAnimation) {
		if (withoutAnimation) {
			if (this.orientation == orientations.horizontal) {
				this.setLeft(newPosition);
			} else {
				this.setTop(newPosition);
			}
		} else {
			if (this.orientation == orientations.horizontal) {
				$(this.panel).animate({ 'left': newPosition.toString() }, 200);
			} else {
				$(this.panel).animate({ 'top':newPosition.toString() }, 200);
			}
		}
    }
	
	this.slideToInit = function (withoutAnimation) {
		if (this.orientation == orientations.horizontal) {
				this.slide(this.initLeft, withoutAnimation);
			} else {
				this.slide(this.initTop, withoutAnimation);
			}
	}
    
    this.hide = function()
    {
        $(this.panel).css('visibility', 'hidden');
    }
    
    this.show = function()
    {
        $(this.panel).css('visibility', 'visible');
    }
   
    
    /*
        Sets new element index (blurs old one and focuses new)
        
        *newIndex - index of the new element
    */
    this.setIndex = function (newIndex) {
        /*if visible num setted*/
        if (this.hideElements && this.index > newIndex)
        {
            var element = $(this.elements[this.index + this.visibleNum], this.panel);
            Logger.write("hide elem="+this.index + this.visibleNum, "SlidingPanel");
            element.hide();
        }    
        /*if visible num setted*/        
        
        
        if (newIndex >= 0 && newIndex < this.elements.length)
        {
            this.blurElement(this.index);
            this.focusElement(newIndex);
        }
        
        /*if visible num setted*/
		this.showVisibleNum();
          /*if visible num setted*/ 
    }
    
    /*
    * Shows visible elements
    */
    this.showVisibleNum = function () {
        for (var i = this.index; i < (this.index + this.visibleNum); i++) {
            var elem = $(this.elements[i], this.panel);                
            elem.show();
        }
    }
    
    /*
        Focuses panel
    */
    this.focusPanel = function()
    {
		this.isFocused = true;
        Logger.write("=====Focusing panel", "SlidingPanel");
        $(this.panel).addClass("focused");
		this.focusElement(this.index);
    }
    
    /*
        Blurs panel
    */
    this.blurPanel = function()
    {
		this.isFocused = false;
        Logger.write("=====Bluring panel", "SlidingPanel");
        var element = $(this.elements[this.index], this.panel);
		$(this.panel).removeClass("focused");
		//element.removeClass("focused");
		if (this.orientation == orientations.vertical) {
			if($(element).hasClass("folder")) {
				$(this.elements[this.index] + " > .bracketRight").addClass("folderImg");
				$(this.elements[this.index] + " > .bracketRight").removeClass("folderImgW");
			}
		}
    }
    
    /*
        Focuses next element
    */
    this.focusNext = function()
    {
        this.setIndex(this.index + 1);
    }
    
    /*
        Focuses previous element
    */
    this.focusPrev = function()
    {
        this.setIndex(this.index - 1);
    }
    
    /*
        Get focused element
    */
    this.getFocused = function()
    {
        return $(this.elements[this.index], this.panel);
    }
    
    this.getFocusedId = function()
    {
        return this.elements[this.index];
    }
	
	this.getTotal = function() {
		return this.elements.length;
	}
	
	this.getCurrentPosition = function () {
		if (this.orientation == orientations.horizontal) {
			return parseInt($(this.panel).css("left"));
		} else {
			return parseInt($(this.panel).css("top"));
		}
	}
    
    this.loadData(elements);
    elements.length = 0;
    elements = null;
}