(function () {
	'use strict';

    var ng_module_name = 'pageurl_list';

	angular.module(ng_module_name)
		.directive('pageurlList', pageurlList);

	pageurlList.$inject = ['pageurlListService', 'newPageService', 'siteLinkService', 'deletePageurlService'];
	function pageurlList(pageurlListService, newPageService, siteLinkService, deletePageurlService)
	{
		return {
			replace: false,
			restrict: 'E',
			controller: controller,
			controllerAs: 'list',
			templateUrl: '/intranet/pages/html/includes/pageurl_list.directive.html'
		};

		function controller()
		{
			var ctrl = this;
			ctrl.urlTree = [];
			ctrl.perms = {};

			ctrl.init = function()
			{
				pageurlListService.registerDataCallback(ctrl.addLevels);
				ctrl.urlTree = pageurlListService.getUrls();
				ctrl.perms = pageurlListService.getPerms();
				newPageService.hide();

				ctrl.addLevels();
			};

			ctrl.addLevels = function()
			{
				if (ctrl.urlTree.length === 0)
					return;

				ctrl.urlTree[0].level = 0;
				for (var i = 0; i < ctrl.urlTree[0].children.length; i++)
				{
					var item = ctrl.urlTree[0].children[i];
					item.level = 1;

					for (var j = 0; j < item.children.length; j++)
					{
						item.children[j].level = 2;
					}
				}
			};

			ctrl.addPage = function($event, pageurl)
			{
				var parentName = ctrl.urlTree[0].title;
				if (pageurl.parent_id > 0)
				{
					for (var i = 0; i < ctrl.urlTree[0].children.length; i++)
					{
						var data = ctrl.urlTree[0].children[i];
						if (data.id === pageurl.parent_id)
							parentName = data.title;
					}
				}
				$event.preventDefault();
				newPageService.setData(pageurl, parentName);
				newPageService.show();
			};

			ctrl.newPageSubmitted = function(data)
			{
				pageurlListService.addPage(data, ctrl.init);
			};

			ctrl.addLink = function($event, pageurl)
			{
				var parentName = ctrl.urlTree[0].title;
				if (pageurl.parent_id > 0)
				{
					for (var i = 0; i < ctrl.urlTree[0].children.length; i++)
					{
						var data = ctrl.urlTree[0].children[i];
						if (data.id === pageurl.parent_id)
							parentName = data.title;
					}
				}
				$event.preventDefault();
				siteLinkService.setNewData(pageurl, parentName);
				siteLinkService.show();
			};

			ctrl.editLink = function($event, pageurl)
			{
				var parentName = ctrl.urlTree[0].title;
				if (pageurl.parent_id > 0)
				{
					for (var i = 0; i < ctrl.urlTree[0].children.length; i++)
					{
						var data = ctrl.urlTree[0].children[i];
						if (data.id === pageurl.parent_id)
							parentName = data.title;
					}
				}
				$event.preventDefault();
				siteLinkService.setEditData(pageurl, parentName);
				siteLinkService.show();
			};

			ctrl.linkSubmitted = function(data)
			{
				pageurlListService.editLink(data, ctrl.init);
			};

			ctrl.deletePageurl = function($event, pageurl)
			{
				$event.preventDefault();

				deletePageurlService.setData(pageurl);
				deletePageurlService.show();
			};

			ctrl.deletePageurlConfirmed = function(data)
			{
				pageurlListService.deletePageurl(data, ctrl.init);
			};

			newPageService.registerSubmitCallback(ctrl.newPageSubmitted);
			siteLinkService.registerSubmitCallback(ctrl.linkSubmitted);
			deletePageurlService.registerSubmitCallback(ctrl.deletePageurlConfirmed);

			ctrl.toggleVisibility = function($event, pageUrl)
			{
				$event.preventDefault();

				pageurlListService.toggleVisibility(pageUrl);

			};

			ctrl.canEdit = function()
			{
				return ctrl.perms.canEdit;
			};

			ctrl.canDelete = function()
			{
				return ctrl.perms.canDelete;
			};

			/**
			 * Called when a drag and drop item is moved within the same list
			 *
			 * @param event
			 */
			function itemOrderChanged(event)
			{
				var item = event.source.itemScope.$parent.pageUrl;

				// Resolve display orders for the new and old locations.
				// Easiest to just update all display_orders rather than just look for the right parent
				for (var i = 0; i < ctrl.urlTree[0].children.length; i++)
				{
					var menuItem = ctrl.urlTree[0].children[i];
					menuItem.display_order = i + 1;

					for (var j = 0; j < menuItem.children.length; j++)
					{
						menuItem.children[j].display_order = j + 1;
					}
				}

				pageurlListService.orderChanged(item, function()
				{
					// Callback to update the page list
					ctrl.init();
				});
			}

			/**
			 * Called when a drag and drop item is moved between lists
			 *
			 * @param event
			 */
			function itemMoved(event)
			{
				var item = event.source.itemScope.$parent.pageUrl;

				// The tree will already be up to date, we just need up update the parent_id and level of the item
				// Also update all display orders to make sure they get saved in the current order
				var parent = ctrl.urlTree[0].id;
				for (var i = 0; i < ctrl.urlTree[0].children.length; i++)
				{
					// Update the display order as we go
					var menuItem = ctrl.urlTree[0].children[i];
					menuItem.display_order = i + 1;

					if (menuItem.id === item.id)
					{
						menuItem.parent_id = parent;
						menuItem.level = 1;
					} else
					{
						var subParent = menuItem.id;
						for (var j = 0; j < menuItem.children.length; j++)
						{
							// Update the display order as we go
							menuItem.children[j].display_order = j + 1;

							if (menuItem.children[j].id === item.id)
							{
								menuItem.children[j].parent_id = subParent;
								menuItem.children[j].level = 2;
							}
						}
					}
				}

				pageurlListService.itemMoved(item, function()
				{
					// Callback to update the page list
					ctrl.init();
				});
			}

			/**
			 * Called whenever a dragged item is moved over a sub-item droppable container to assess whether it should
			 * allow dropping. Prevents links having children and pages with children being dropped (sub-pages can't
			 * have child pages).
			 *
			 * @param sourceItemHandleScope
			 * @param destScope
			 * @returns boolean
			 */
			function itemAccept(sourceItemHandleScope, destScope)
			{
				// All pages can accept children
				var willAllowChildLink = destScope.$parent.pageUrl.type === 'page';
				if (!willAllowChildLink)
				{
					// A link can have a link child
					if (sourceItemHandleScope.itemScope.$parent.pageUrl.type === 'link')
						willAllowChildLink = true;
				}

				// Can't drop an item with children into a sub-item because that would make the tree 3 levels deep
				var sourceHasChildren = sourceItemHandleScope.itemScope.$parent.pageUrl.children.length > 0;

				return (willAllowChildLink && !sourceHasChildren);
			}

			ctrl.dragTopListener =
			{
				orderChanged: itemOrderChanged,
				itemMoved: itemMoved,
                containment: ".js-drag-container",
                containerPositioning: 'relative'
			};

			ctrl.dragSubListener =
			{
				accept: itemAccept,
				orderChanged: itemOrderChanged,
				itemMoved: itemMoved,
                containment: ".js-drag-container",
                containerPositioning: 'relative'
			};

			ctrl.getTarget = function(pageUrl)
			{
				var target = '_parent';
				if (pageUrl.new_window)
					target="_window";

				return target;
			};
		}
	}
}());
