//////////////////////////////////////////////////////////////////////////////////////////////////
// feedreader.js -- Main javascript file for CS::FeedReader
// 
//////////////////////////////////////////////////////////////////////////////////////////////////

function Reader (variableName, treeViewName, listingCallbackName, displayCallbackName, readFeedCallbackName, rootMenuName, folderMenuName, feedMenuName, moveNodeCallbackName) 
{
	this.variableName = variableName;
	this.treeViewName = treeViewName;
	this.listingCallbackName = listingCallbackName;
	this.displayCallbackName = displayCallbackName;
	this.readFeedCallbackName = readFeedCallbackName;
	this.rootMenuName = rootMenuName;
	this.folderMenuName = folderMenuName;
	this.feedMenuName = feedMenuName;
	this.moveNodeCallbackName = moveNodeCallbackName;

	// Click Handlers
	/////////////////////////
	// Function: treeContextMenu
	// This function is called when you right click on a node in the tree view control.
	this.OpenContextMenu = function (treeNode, e)
	{
		// First, force the tree to select the node that was right-clicked. Otherwise, it can cause some issues.
		if (this.GetTreeView().SelectedNode == null || this.GetTreeView().SelectedNode.ID != treeNode.ID)
			this.GetTreeView().SelectNodeById(treeNode.ID);

		// Determine whether we need to show the folder menu or feed menu, depending on what the
		// user right-clicked.
		if (treeNode.ID == 'folder-0-0')
			this.GetRootMenu().ShowContextMenu(e, treeNode);
		else if (treeNode.ID.indexOf('folder') >= 0)
			this.GetFolderMenu().ShowContextMenu(e, treeNode); 
		else if (treeNode.ID.indexOf('feed') >= 0)
			this.GetFeedMenu().ShowContextMenu(e, treeNode); 
	}

	// Function: contextMenuClickHandler
	// This function is what is called when you click on an item in a right-click context menu.
	this.ClickContextMenuItem = function(menuItem)
	{
		var contextDataNode = menuItem.ParentMenu.ContextData;
		var targetPage = 'unknown.html';
		var popWindow = true;
		var height = 250;
		var width = 500;
		var callbackHandler = null;

		switch (menuItem.ID)
		{
			case 'importOpml':
				targetPage = 'ImportOpml.aspx';
				break;
			case 'exportOpml':
				window.location = 'ExportOpml.aspx';
				popWindow = false;
				break;
			case 'folderNewFolder':
			case 'newFolder':
				targetPage = 'AddFolder.aspx';
				height = 130;
				width = 550;
				callbackHandler = new Function('data', this.variableName + '.UpdateFolder(data);');
				break;
			case 'folderNewFeed':
			case 'newFeed':
				targetPage = 'AddFeed.aspx';
				height = 130;
				callbackHandler = new Function('data', this.variableName + '.UpdateFolder(data);');
				break;
			case 'deleteFolder':
				this.DeleteFolder(contextDataNode.ID);
				popWindow = false;
				break;
			case 'deleteFeed':
				this.DeleteFeed(contextDataNode.ID);
				popWindow = false;
				break;
			case 'feedProperties':
				targetPage = 'FeedProperties.aspx';
				width = 600;
				height = 300;
				break;
			default:
				targetPage = 'unknown.html';
				break;	
		}
		
		if (popWindow)
			Telligent_Modal.Open(targetPage + '?ID=' + encodeURI(contextDataNode.ID), width, height, callbackHandler);
			
		return true;	
	}

	this.UpdateFolder = function (data)
	{
		if (!data)
			return;

		var tree = this.GetTreeView();
		var node = tree.FindNodeById(data[0]);
		var i;
		
		for (i = 0; i < data[1].length; i++)
		{
			node.SetProperty(data[1][i][0], data[1][i][1]);
		}
		
		node.SetProperty('Expanded', false);
		node.ClearChildren();
		tree.Render();		
		
		window.setTimeout('try { ' + this.variableName + '.GetTreeView().FindNodeById(\'' + data[0] + '\').Expand(); } catch (err) { }', 249);
	}

	this.DeleteFolder = function (nodeId)
	{
		var doDelete = false;
		var node = this.GetTreeView().SelectedNode
		
		// First, do business rules.
		if (node.Nodes().length > 0)
		{
			alert('This folder still contains items. Please delete all items from this folder before deleting it.');
			return;
		}
		
		if (nodeId.indexOf('folder') < 0)
		{
			// Somehow, the user has called deleteFolder on a non-Folder node.
			return;
		}
		
		// Confirm the deletion
		doDelete = confirm('Are you sure you want to delete this folder?');
		if (doDelete)
		{
			// Do the callback and delete the folder
			ReaderAJAX.DeleteFolder(this.variableName, nodeId, this.ProcessAjaxResponse);

			// Remove the node on the client-side
			node.Remove();
			this.GetTreeView().Render();
		}
	}

	this.DeleteFeed = function (nodeId)
	{
		var doDelete = false;
		
		// First, do business rules.	
		if (nodeId.indexOf('feed') < 0)
		{
			// Somehow the user has called deleteFeed on a non-Feed node.
			return;
		}
		
		doDelete = confirm('Are you sure you want to delete this feed?');
		if (doDelete)
		{
			ReaderAJAX.DeleteFeed(this.variableName, nodeId, this.ProcessAjaxResponse);
			
			this.GetTreeView().SelectedNode.Remove();
			this.GetTreeView().Render();
		}
	}

	// Function: tvFolderList_OnNodeSelect
	// This function is called when you actually select a feed in the treeview.
	this.SelectTreeNode = function(node)
	{
		if (node.ID.indexOf('folder') < 0)
		{
			// If it's a folder node selected, call back on the post listing.
			this.GetListingCallback().Callback(node.ID);
			this.GetDisplayCallback().Callback(node.ID + '-feedsummary');
		}
		else
		{
			// If it is a folder node, call back on the post display so that the folder summary is displayed.
			this.GetDisplayCallback().Callback(node.ID + '-' + node.Text + '-foldersummary');
		}
	}

	// Function: tvFolderList_OnNodeRename
	// This function is called whenever a node is renamed. This does basic business rule validation and then
	// does a client callback to update the database accordingly.
	this.RenameTreeNode = function (node, name)
	{
		var doRename = false;
		
		// Ignore the rename if they don't make any changes.
		if (node.Text == name) return false;
		
		// Ignore the rename of the very root folder.
		if (node.ID == 'folder-0-0') return false;
		
		// Do some validation of the newly renamed string.
		// First, invalid characters.
		if (!this.CheckValidCharacters(name))
		{
			alert('Invalid characters entered. Please do not use: \\/:*?"<>|');
			return false;
		}
		
		// Next, let's make sure the new folder name isn't too long.
		if (name.length > 50)
		{
			alert('The new folder name is too long. Please make it 50 characters or less. The folder name was ' + name.length + ' characters long.');
			return false;
		}
		
		// Otherwise, let's confirm the rename.	
		doRename = confirm('Are you sure you want to rename \"' + node.Text + '\" to \"' + name + '\"?');
		if (doRename)
		{
			// Do the rename callback.
			ReaderAJAX.RenameFolder(this.variableName, node.ID, name, this.ProcessAjaxResponse);
		}
		
		return doRename;
	}

	// Function: rPosts_OnPostSelect
	// This function is called when you select a post within the post listing display.
	this.SelectPost = function (feedPostId, markRead)
	{
		// Determine whether or not we need to do mark this read.
		if (markRead)
			ReaderAJAX.MarkPostRead(this.variableName, feedPostId, this.ProcessAjaxResponse);
		
		// Call out to display the post body.
		this.GetDisplayCallback().Callback(feedPostId);
	}

	this.MoveTreeNode = function (sourceNode, targetNode)
	{
		var doMove = false;
		
		if (targetNode.ID.indexOf('feed') >= 0)
		{
			alert('You cannot move anything into a feed node, sorry.');
			return false;
		}
		
		doMove = confirm('Are you sure you want to move \"' + sourceNode.Text + '\" to \"' + targetNode.Text + '\"?');
		if (doMove)
			ReaderAJAX.MoveNode(this.variableName, sourceNode.ID, targetNode.ID, this.ProcessAjaxResponse);

		return doMove;
	}
	
	this.ProcessAjaxResponse = function(result)
	{
		if (result.error)
			alert(result.error);
	}

	// Accessor Functions
	///////////////////////////
	this.GetTreeView = function()
	{
		return eval(this.treeViewName);
	}

	this.GetListingCallback = function()
	{
		return eval(this.listingCallbackName);
	}

	this.GetDisplayCallback = function()
	{
		return eval(this.displayCallbackName);
	}

	this.GetReadFeedCallback = function()
	{
		return eval(this.readFeedCallbackName);
	}

	this.GetRootMenu = function()
	{
		return eval(this.rootMenuName);
	}

	this.GetFolderMenu = function()
	{
		return eval(this.folderMenuName);
	}

	this.GetFeedMenu = function()
	{
		return eval(this.feedMenuName);
	}

	this.GetMoveNodeCallback = function()
	{
		return eval(this.moveNodeCallbackName);
	}

	// Utility Functions
	///////////////////////////
	this.CheckValidCharacters = function(inputString)
	{
		if (inputString.indexOf('\\') >= 0 ||
			inputString.indexOf('/') >= 0 ||
			inputString.indexOf(':') >= 0 ||
			inputString.indexOf('*') >= 0 ||
			inputString.indexOf('?') >= 0 ||
			inputString.indexOf('\"') >= 0 ||
			inputString.indexOf('<') >= 0 ||
			inputString.indexOf('>') >= 0 ||
			inputString.indexOf('|') >= 0)
		{
			return false;
		}
		else
		{
			return true;
		}
	}
}