function NGSPanelItem(domElement)
{
	this.DomElement = domElement;
	
	this.LinkElement = NGSPanelbar.GetFirstChildByTagName(this.DomElement, "a");
	
	if (this.LinkElement == null)
	{
		
		this.ID = this.DomElement.id;
		this.TextElement = NGSPanelbar.GetFirstChildByTagName(this.DomElement, "span");
		this.NavigateUrl = "";	
	}
	else
	{
		this.ID = this.LinkElement.id;
		this.TextElement = NGSPanelbar.GetFirstChildByTagName(this.LinkElement, "span");
		this.NavigateUrl = this.LinkElement.href;
	}
		
	this.IsSeparator = false;
	this.AnimationContainer = null;
	this.ExpandedItem = null;
	this.FocusedItem = null;
	this.Items =  [];
	this.Attributes = {};
	this.Index = -1;
	this.Level = -1;
	this.Parent = null;
	this.Panelbar = null;
	this.TimeoutPointer = null;
	this.Templated = false;
	
	// css classes, load from the server
	this.FocusedCssClass = "focused";
	this.SelectedCssClass = "selected";
	this.ClickedCssClass = "clicked";
	this.ExpandedCssClass = "expanded";
	this.DisabledCssClass = "disabled";
	this.CssClass = "";
	
	this.Focused = false;
	this.Clicked = false;
	this.Enabled = true;
	this.Expanded = false;
	this.EaseInProgress = false;
	
	this.Initialized = false;
	
	this.ImageOverUrl = "";
	this.ExpandedImageUrl = "";
	this.DisabledImageUrl = "";
}


NGSPanelItem.prototype.SetText = function (text)
{
	this.TextElement.innerHTML = text;
	this.Text = text;
	this.RecordState();
}

NGSPanelItem.prototype.SetValue = function (value)
{
	this.Value = value;
	this.RecordState();
}

NGSPanelItem.prototype.GetHeight = function ()
{
	return this.Parent.Expanded || this.Parent == this.Panelbar ? this.LinkElement.offsetHeight : 0;
}

NGSPanelItem.prototype.InitializeDomElements = function()
{
	this.AnimationContainer = NGSPanelbar.GetFirstChildByClassName(this.DomElement, "slide");
	this.ImageElement = NGSPanelbar.GetFirstChildByTagName(this.LinkElement || this.DomElement, "img");
	
	if (this.ImageElement)
	{
		this.ImageUrl = this.ImageElement.src;
	}
		
	if (this.AnimationContainer)
	{
		var ul = this.AnimationContainer.getElementsByTagName("ul")[0];
		
		this.ChildItemList = ul;
	}
}

NGSPanelItem.prototype.Initialize = function ()
{

	NGSControlsNamespace.DomEventMixin.Initialize(this);

	this.LoadConfiguration();

	this.InitializeDomElements();



		
	if (this.AnimationContainer)
	{
		
		this.Ease = new NGSControlsNamespace.Ease(
			this.ChildItemList, 
			this.Panelbar, 
			0,
			0,
			this
		); 

		this.Ease.SlideParent = true;
	
		var expandDirection = "down";
		var easeProperty = NGSPanelbarNamespace.ExpandDirectionPropertyName[expandDirection];
		
		this.Ease.SetSide("top");
		this.AnimationContainer.style.zIndex = this.GlobalIndex + 10;
		this.ChildItemList.style.zIndex = this.GlobalIndex + 10;
	}
	
	if (this.TextElement && this.TextElement.firstChild)
	{
	
		this.Text = this.TextElement.firstChild.nodeValue;
	}
	
	this.OriginalZIndex = this.DomElement.style.zIndex;
	
	this.AttachEventHandlers();
	this.RenderAccessKey();

	this.Initialized = true;	
	NGSPanelbar.CreateState(this);
	
	this.UpdateCssClass();
	

};


NGSPanelItem.prototype.RenderAccessKey = function ()
{
	if (this.IsSeparator || !this.LinkElement)
	{
		return;
	}
	
	var accessKey = this.LinkElement.accessKey.toLowerCase();
	
	// If accessKey is not set
	if (!accessKey)
	{
		return;
	}
	var text = this.TextElement.firstChild.nodeValue;
	var indexOfAccessKey = text.toLowerCase().indexOf(accessKey);
	
	// If accesKey is not found
	if (indexOfAccessKey == -1)
	{
		return;
	}
	
	this.TextElement.innerHTML = 
		text.substr(0, indexOfAccessKey) + 
		"<u>" + 
		text.substr(indexOfAccessKey,  1) + 
		"</u>" + 
		text.substr(indexOfAccessKey + 1, text.length);
}


NGSPanelItem.prototype.Dispose = function ()
{
	if (!this.Initialized) return;
	this.DisposeDomEventHandlers();
	if (this.Ease)
	{
		this.Ease.Dispose();
	}
	this.DomElement = null;
	this.LinkElement = null;	
	this.AnimationContainer = null;	
}

NGSPanelItem.prototype.Focus = function ()
{
	if (!this.CanFocus())
	{
		return;
	}
	
	if ((!this.Parent.Expanded) && this.Parent.Expand)
	{
		this.Parent.Expand();
	}

	this.Parent.FocusedItem = this;
	
	if (!this.Focused && this.LinkElement)
	{
		this.LinkElement.focus();
	}
	
	this.UpdateCssClass();
	
	this.RaiseEvent("OnClientItemFocus");
}

NGSPanelItem.prototype.Blur = function ()
{
	if (this.IsSeparator)
	{
		return;
	}
	
	if (this.Focused)
	{
		this.LinkElement.blur();
	}
	this.Parent.FocusedItem = null;
	this.UpdateCssClass();
	this.RaiseEvent("OnClientItemBlur");
}

NGSPanelItem.prototype.SetChildrenHeight = function (value)
{
	if (value < 0) value = 0;
	if (!value == "") value += "px";
	
	this.ChildItemList.style.height = value;
	this.AnimationContainer.style.height = value;
	
}

NGSPanelItem.prototype.UpdateChildrenWidth = function ()
{
	this.AnimationContainer.style.display = "none"; 
	this.ChildItemList.style.display = "none";
	this.ChildItemList.style.width = this.DomElement.offsetWidth + "px";
	this.AnimationContainer.style.width = this.DomElement.offsetWidth + "px";
	this.ChildItemList.style.display = "block";
	this.AnimationContainer.style.display = "block";
}

NGSPanelItem.prototype.InstantExpand = function ()
{
	if (!this.Ease) return;
	var type = this.Ease.ExpandConfig.Type;
	this.Ease.ExpandConfig.Type = "None";
	this.Expand();
	this.Ease.ExpandConfig.Type = type;
}
	
NGSPanelItem.prototype.Expand = function ()
{	
	if (!this.Items.length)
	{
		return;
	}
	
	if (this.Expanded)
	{
		return;
	}

	if (this.Level == 1 && 	this.Panelbar.FullExpandedItem)
	{
		this.ChildItemList.style.height = this.Panelbar.GetGroupHeight() + "px";
	}
	
	this.ChildItemList.style.display = "none";
	this.ChildItemList.style.width = this.DomElement.offsetWidth + "px";
	
	if (this.Level > 1 && !this.Panelbar.FullExpandedItem)
	{
		this.Parent.SetChildrenHeight("");
	}
	
	
		
	if (this.Parent.ExpandedItem && this.Panelbar.SingleExpandedItem)
	{
		this.Parent.ExpandedItem.Collapse();
	}
	
	this.Parent.ExpandedItem = this;
	this.Panelbar.LastExpandedItem = this;
	
	this.Expanded = true;
	
	var documentSize = NGSControlsNamespace.Screen.GetViewPortSize();
	
	this.ChildItemList.style.display = "block";
		
	this.Ease.ShowElements();
	
	this.Ease.SetSide("top");


	this.EaseInProgress = true;
	this.Ease.In();
	
	
	this.UpdateCssClass();

	this.RecordState();
	this.RaiseEvent("OnClientItemExpand");
	
	this.CallNGSShow();
};	

NGSPanelItem.prototype.CallNGSShow = function ()
{
	var children = this.ChildItemList.getElementsByTagName("*");
	
	for (var i = 0; i < children.length; i ++)
	{
		var child = children[i];
		if (child.NGSShow)
		{
			child.NGSShow();
		}
	}
}

NGSPanelItem.prototype.RaiseEvent = function(eventName)
{
	return this.Panelbar.RaiseEvent(eventName, {Item:this});
}

NGSPanelItem.prototype.UpdateCssClass = function ()
{
	if (this.IsSeparator || !this.LinkElement)
	{
		return;
	}
	
	var cssClass = "link " + this.CssClass;
	
	if (this.Focused)
	{
		cssClass = cssClass + " " + this.FocusedCssClass;
	}
	
	if (this.Selected)
	{
		cssClass = cssClass + " " + this.SelectedCssClass;
	}	

	if (this.Expanded)
	{
		cssClass = cssClass + " " + this.ExpandedCssClass;
	}

	if (this.Clicked)
	{
		cssClass = cssClass + " " + this.ClickedCssClass;
	}

    if (!this.Enabled)
    {
        cssClass = cssClass + " " + this.DisabledCssClass;
    }

	this.LinkElement.className = cssClass;
	
	this.UpdateImageUrl();
}

NGSPanelItem.prototype.UpdateImageUrl = function ()
{
	if (!this.ImageElement) return;

	var newUrl = this.ImageUrl;

	if (this.Hovered && this.ImageOverUrl)
	{
		newUrl = this.ImageOverUrl;
	}

	if (this.Selected && this.SelectedImageUrl)
	{
		newUrl = this.SelectedImageUrl;
	}

	if (this.Expanded && this.ExpandedImageUrl)
	{
		newUrl = this.ExpandedImageUrl;
	}
	
	if (!this.Enabled && this.DisabledImageUrl)
	{
		newUrl = this.DisabledImageUrl;
	}
	
	if (newUrl != this.ImageElement.src)
	{
		this.ImageElement.src = newUrl;
	}
}


NGSPanelItem.prototype.Enable = function ()
{
	if (this.IsSeparator)
	{
		return;
	}
	
	this.LinkElement.disabled = "";	
	this.Enabled = true;
	this.EnableDomEventHandling();
	this.UpdateCssClass();
}

NGSPanelItem.prototype.Disable = function ()
{
	if (this.IsSeparator)
	{
		return;
	}
	
	if (this.LinkElement)
	{
	    this.LinkElement.disabled = "disabled";	
	}
	this.Enabled = false;
	this.DisableDomEventHandling();
	this.UpdateCssClass();
}
	
NGSPanelItem.prototype.Collapse = function ()
{

	if (!this.Items.length)
	{
		return;
	}
	
	if (this.IsSeparator)
	{
		return;
	}
	
    if (!this.Expanded)
	{
		return;
    }
    
    
	this.Parent.ExpandedItem = null;
	
	this.Parent.LastExpandedItem = this.Parent;

	this.Expanded = false;
	
	if (this.Level > 1 && !this.Panelbar.FullExpandedItem)
	{
		this.Parent.SetChildrenHeight("");
	}
		
	
	this.EaseInProgress = true;
	this.Ease.Out();
	
	this.UpdateCssClass();
	
    this.RecordState();
    this.RaiseEvent("OnClientItemCollapse");
};

NGSPanelItem.prototype.OnCollapseComplete = function()
{
	this.EaseInProgress = false;
}


NGSPanelItem.prototype.OnExpandComplete = function()
{
	this.EaseInProgress = false;
	this.AnimationContainer.style.height = "auto";
}



NGSPanelItem.prototype.Select = function ()
{
	if (this.Selected) return;
	if (this.Panelbar.SelectedItem)
	{
		this.Panelbar.SelectedItem.UnSelect();
	}
	
	this.Panelbar.SelectedItem = this;
	this.Selected = true;

	this.RecordState();
	this.UpdateCssClass();
}

NGSPanelItem.prototype.UnSelect = function ()
{
	if (!this.Selected) return;
	this.Panelbar.SelectedItem = null;
	this.Selected = false;
	
	this.RecordState();
	this.UpdateCssClass();
}

/**
 * Event handlers
 */

NGSPanelItem.prototype.AttachEventHandlers = function ()	
{
	if (this.IsSeparator || !this.LinkElement)
	{
		return;
	}

	this.AttachDomEvent(this.LinkElement, "mouseout", "HRefMouseOutHandler");
	this.AttachDomEvent(this.LinkElement, "mouseover", "HRefMouseOverHandler");
	
	this.AttachDomEvent(this.LinkElement, "click", "ClickHandler", true);
	
	this.AttachDomEvent(this.LinkElement, "mousedown", "MouseDownHandler");
	this.AttachDomEvent(this.LinkElement, "mouseup", "MouseUpHandler");
	
	this.AttachDomEvent(this.LinkElement, "blur", "BlurHandler");
	this.AttachDomEvent(this.LinkElement, "focus", "FocusHandler");
	
	this.AttachDomEvent(this.LinkElement, "keydown", "KeyDownHandler");
	
	this.AttachDomEvent(window, "load", "WindowLoadHandler");
};

NGSPanelItem.prototype.WindowLoadHandler = function (e) 
{
	if (this.LoadHandlerExecuted)
	{
		return;
	}
	
	this.LoadHandlerExecuted = true;
	
    if (this.Expanded)
    {
		this.Expanded = false;
		this.Parent.ExpandedItem = this;
		this.InstantExpand();	
    }
}

NGSPanelItem.prototype.MouseDownHandler = function (e)
{
	this.Clicked = true;
	this.UpdateCssClass();
}

NGSPanelItem.prototype.MouseUpHandler = function (e)
{
	this.Clicked = false;
	this.UpdateCssClass();
}

NGSPanelItem.prototype.HRefMouseOutHandler = function (e)
{
	var to = NGSControlsNamespace.DomEvent.GetRelatedTarget(e);
	
	if (this.Panelbar.IsChildOf(this.LinkElement, to) || to == this.LinkElement)
	{
		return;
	}

	this.Hovered = false;
	
	this.UpdateCssClass();

	this.RaiseEvent("OnClientMouseOut");
}

NGSPanelItem.prototype.HRefMouseOverHandler = function (e)
{
	var from = NGSControlsNamespace.DomEvent.GetRelatedTarget(e);
	if (this.Panelbar.IsChildOf(this.LinkElement, from) || this.LinkElement == from)
	{
		return;
	}
	
	this.Hovered = true;
	
	this.UpdateCssClass();
	
	this.RaiseEvent("OnClientMouseOver");
}

NGSPanelItem.prototype.KeyDownHandler = function (e)
{
	var arrows = {left : 37, up : 38, right : 39, down : 40, esc : 27 };
	
	var keyCode = NGSControlsNamespace.DomEvent.GetKeyCode(e);
	
	if (keyCode == arrows.up)
	{
		this.HandleUpArrow();	
	}
	else if (keyCode == arrows.down)
	{
		this.HandleDownArrow();
	}
	
	else if (keyCode == arrows.esc)
	{
		this.Parent.Focus();
	}
	else
	{
		return;
	}
	
	NGSControlsNamespace.DomEvent.PreventDefault(e);

}


NGSPanelItem.prototype.FocusHandler = function (e)
{
	this.Focused = true;
	this.Focus();
}


NGSPanelItem.prototype.BlurHandler = function (e)
{
	this.Focused = false;
	this.Panelbar.Clicked = false;
	this.Blur();
}

NGSPanelItem.prototype.NavigatesToURL = function ()
{
	if (location.href + "#" == this.NavigateUrl || location.href == this.NavigateUrl)
	{
	    return false;
	}
	return (new RegExp("//")).test(this.LinkElement.href);
}	

NGSPanelItem.prototype.Validate = function ()
{
	if (!this.Panelbar.CausesValidation || this.NavigatesToURL())
	{
		return true;
	}
	
	if (typeof (Page_ClientValidate) != 'function')
	{
		return true;
	}
	
	return Page_ClientValidate(this.Panelbar.ValidationGroup);
}


NGSPanelItem.prototype.ClickHandler = function (e)
{
	if (!this.Enabled)
	{
		NGSControlsNamespace.DomEvent.PreventDefault(e);
		return false;
	}
	
    if (!this.RaiseEvent("OnClientItemClicking"))
	{
		NGSControlsNamespace.DomEvent.PreventDefault(e);
		return false;
	}
    
    if (!this.Validate())
    {
        return false;    
    }
    
    var javaScriptUrl = this.LinkElement.href.indexOf("javascript:") == 0;
    
    if (this.NavigateAfterClick && !javaScriptUrl)
    {
		if (this.Panelbar.SingleExpandedItem)
		{
			if (this.Parent.ExpandedItem)
			{
				this.Parent.ExpandedItem.Expanded = false;
				this.Parent.ExpandedItem.RecordState();
			}
			if (this.Items.length)
			{
				this.Expanded = true;
			}
		
		}
		else if (this.Items.length)
		{
			this.Expanded = !this.Expanded;
		}
		
		if (this.Panelbar.SelectedItem)
		{
			this.Panelbar.SelectedItem.Selected = false;
			this.Panelbar.SelectedItem.RecordState();
		}
		
		this.Panelbar.SelectedItem = this;
		this.Selected = true;
		
        this.RaiseEvent("OnClientItemClicked");
		this.RecordState();
		return true;
    }
    
    if (this.Panelbar.SingleExpandedItem)
	{
		if (!this.Expanded) this.Expand();
    }
	else
	{
		this.Expanded ? this.Collapse() : this.Expand();
	}
	
	this.Select();
	
	this.RaiseEvent("OnClientItemClicked");


	if (javaScriptUrl)
	{	
		return true;
	}
	
	NGSControlsNamespace.DomEvent.PreventDefault(e);
	return false;
}


/*
 * Private (sort of)
 */
 

NGSPanelItem.prototype.SetContainerPosition = function(left, top)
{
	this.AnimationContainer.style.top = (top + this.GroupSettings.OffsetY) + "px";
	this.AnimationContainer.style.left = (left + this.GroupSettings.OffsetX) + "px";
}


NGSPanelItem.prototype.SetAttribute = function (name, value)
{
	this.Attributes[name] = value;
	this.RecordState();
}

NGSPanelItem.prototype.SetImageUrl = function (src)
{
	this.ImageUrl = src;
	this.UpdateCssClass();
	this.RecordState();
}

NGSPanelItem.prototype.SetImageOverUrl = function (src)
{
	this.ImageOverUrl = src;
	this.UpdateCssClass();
	this.RecordState();
}

NGSPanelItem.prototype.GetAttribute = function (name)
{
	return this.Attributes[name];
}

NGSPanelItem.prototype.LoadConfiguration = function ()
{
	if (this.Panelbar.ItemData[this.ID])
	{
		for (var property in this.Panelbar.ItemData[this.ID])
		{
			this[property] = this.Panelbar.ItemData[this.ID][property];
		}
	}
};

NGSPanelItem.prototype.ApplyStates = function ()
{
    if (!this.Enabled)   
    {
		this.Disable();
    }
    
    if (this.Selected)
    {
		this.Selected = false;
		this.Select();	
    }
    
    if (this.Panelbar.DomElement.offsetHeight)
    {
		this.WindowLoadHandler(); 
	}
}

/**
 * Keyboard handlers
 */

NGSPanelItem.prototype.HandleRightArrow = function ()
{
	
}

NGSPanelItem.prototype.HandleLeftArrow = function ()
{
	
}

NGSPanelItem.prototype.HandleUpArrow = function ()
{		
	this.Index || !this.Parent.Focus ? this.FocusPreviousItem() : this.Parent.Focus();
}


NGSPanelItem.prototype.HandleDownArrow = function ()
{	
	
	if (this.Expanded)
	{
		this.FocusFirstChild();
		return;
		
	}
	var last = this.Index == this.Parent.Items.length - 1;	
	
	if ( last && this.Parent.Focus)
	{
		this.Parent.FocusNextItem();
	}
	
	else
	{
		this.FocusNextItem();
	}
}


NGSPanelItem.prototype.GetNextItem = function ()
{
	if (this.Index == this.Parent.Items.length - 1)
	{
		return this.Parent.Items[0];
	}
	
	return this.Parent.Items[this.Index + 1];
}

NGSPanelItem.prototype.GetPreviousItem = function ()
{
	if (this.Index == 0)
	{
		return this.Parent.Items[this.Parent.Items.length - 1];
	}
	
	return this.Parent.Items[this.Index - 1];
}

NGSPanelItem.prototype.CanFocus = function ()
{
	return (!this.IsSeparator) && this.Enabled;
}

NGSPanelItem.prototype.FocusFirstChild = function ()
{
	if (!this.Items.length)
	{
		return;
	}
	
	var item = this.Items[0];
	
	while (!item.CanFocus())
	{
		
		item = item.GetNextItem();
		if (item == this.Items[0]) 
		{
			return; // no items to focus
		}
	}
		
	item.Focus();

}

NGSPanelItem.prototype.FocusLastChild = function ()
{
	if (!this.Items.length)
	{
		return;
	}
	
	var item = this.Items[this.Items.length - 1];
	
	while (!item.CanFocus())
	{
		item = item.GetPreviousItem();
		if (this.Items.length - 1) 
		{
			return; // no items to focus
		}		
	}	
	item.Focus();
}



NGSPanelItem.prototype.FocusNextItem = function ()
{
    var item = this.GetNextItem();
	
	while (!item.CanFocus())
	{
		item = item.GetNextItem();
	}	
	item.Focus();
}

NGSPanelItem.prototype.FocusPreviousItem = function ()
{
    var item = this.GetPreviousItem();
	
	while (!item.CanFocus())
	{
		item = item.GetPreviousItem();
	}	
	item.Focus();
}

NGSPanelItem.prototype.RecordState = function ()
{
	// Ignore these properties
	this.InitialState.EaseInProgress = this.EaseInProgress;
	
	var serialized = NGSControlsNamespace.JSON.stringify(this, this.InitialState, NGSPanelbar.JSONIncludeDeep);
	if (serialized == "{}")
	{
		this.Panelbar.ItemState[this.ID] = "";
	}
	else
	{
		this.Panelbar.ItemState[this.ID] = "\"" + this.ID + "\":" + serialized;
	}
	
	this.Panelbar.RecordState();
}

