dojo.provide("dojox.gantt.GanttResourceItem");

dojo.require("dojo.date.locale");

dojo.declare("dojox.gantt.GanttResourceItem", null, {
	constructor: function(ganttchart){
		this.ganttChart = ganttchart;
		this.ownerItem = [];
		this.ownerNameItem = [];
		this.ownerTaskNodeMapping = {};
		this.ownerTaskNodeMapping_time = {};
		this.resourceInfo = {};
		this.ownerTimeConsume = {};
	},
	clearAll: function(){
		this.clearData();
		this.clearItems();
	},
	clearData: function(){
		this.ownerItem = [];
		this.ownerNameItem = [];
		this.ownerTaskNodeMapping = {};
		this.ownerTaskNodeMapping_time = {};
		this.resourceInfo = {};
		this.ownerTimeConsume = {};
	},
	clearItems: function(){
		dojo.destroy(this.content.firstChild);
	},
	buildResource: function(){
		var resourceInfo = {};
		dojo.forEach(this.ganttChart.arrProjects, function(project){
			dojo.forEach(project.arrTasks, function(task){
				task.buildResourceInfo(resourceInfo);
			}, this);
		}, this);
		return resourceInfo;
	},
	buildOwnerTimeConsume: function(){
		var ownerTimeConsume = {};
		for(var owner in this.resourceInfo){
			var tasks = this.resourceInfo[owner];
			//combine time zone  (startTime - this.startDate) / (60 * 60 * 1000) * this.pixelsPerHour;
			var timeZoom = {};
			for(var i = 0; i < tasks.length; i++){
				var task = tasks[i];
				var startTime = task.taskItem.startTime.getTime(), dur = task.taskItem.duration * 24 * 60 * 60 * 1000 / this.ganttChart.hsPerDay;
				timeZoom.min = timeZoom.min ? Math.min(timeZoom.min, startTime) : startTime;
				timeZoom.max = timeZoom.max ? Math.max(timeZoom.max, (startTime + dur)) : (startTime + dur);
			}
			timeZoom.dur = (timeZoom.max - timeZoom.min) * this.ganttChart.hsPerDay / (24 * 60 * 60 * 1000);
			timeZoom.min = new Date(timeZoom.min);
			timeZoom.max = new Date(timeZoom.max);
			ownerTimeConsume[owner] = timeZoom;
		}
		return ownerTimeConsume;
	},
	refresh: function(){
		this.ownerTimeConsume = this.buildOwnerTimeConsume();
		//resize outer div
		this.contentData.firstChild.style.width = Math.max(1200, this.ganttChart.pixelsPerDay * this.ganttChart.totalDays) + "px";
		for(var owner in this.resourceInfo){
			this.refreshOwnerEntry(owner);
		}
	},
	reConstruct: function(){
		this.clearAll();
		this.resourceInfo = this.buildResource();
		this.ownerTimeConsume = this.buildOwnerTimeConsume();
		this.tableControl = dojo.create("table", {
			cellPadding: "0",
			cellSpacing: "0",
			className: "ganttResourceTableControl"
		});
		var newRowTblControl = this.tableControl.insertRow(this.tableControl.rows.length);
		//Add to content Table
		this.contentHeight = this.content.offsetHeight;
		this.contentWidth = this.content.offsetWidth;
		this.content.appendChild(this.tableControl);
		//Creation panel contentData
		this.contentData = dojo.create("div", {className: "ganttResourceContentDataContainer"});
		this.contentData.appendChild(this.createPanelOwners());
		dojo.style(this.contentData, "height", (this.contentHeight - this.ganttChart.panelTimeHeight) + "px");
		//Creation panel of names
		var newCellTblControl = dojo.create("td", {
			vAlign: "top"
		});
		this.panelNames = dojo.create("div", {className: "ganttResourcePanelNames"});
		this.panelNames.appendChild(this.createPanelNamesOwners());
		newCellTblControl.appendChild(this.panelNames);
		newRowTblControl.appendChild(newCellTblControl);
		//add to control contentData and contentDataTime
		newCellTblControl = dojo.create("td", {
			vAlign: "top"
		});
		var divCell = dojo.create("div", {className: "ganttResourceDivCell"});
		divCell.appendChild(this.contentData);
		newCellTblControl.appendChild(divCell);
		newRowTblControl.appendChild(newCellTblControl);
		//Show panel of names
		dojo.style(this.panelNames, {
			height: (this.contentHeight - this.ganttChart.panelTimeHeight - this.ganttChart.scrollBarWidth) + "px",
			width: this.ganttChart.maxWidthPanelNames + "px"
		});
		this.contentData.style.width = (this.contentWidth - this.ganttChart.maxWidthPanelNames) + "px";
		this.contentData.firstChild.style.width = this.ganttChart.pixelsPerDay * (this.ganttChart.panelTime.firstChild.firstChild.rows[3].cells.length) + "px";
		var _this = this;
		this.contentData.onscroll = function(){
			if(_this.panelNames){
				_this.panelNames.scrollTop = this.scrollTop;
			}
		}
		this.contentData.scrollLeft = this.ganttChart.contentData.scrollLeft;
		for(var owner in this.resourceInfo){
			this.createOwnerEntry(owner);
		}
		this.postAdjustment();
	},
	create: function(){
		var resourceHeader = dojo.create("div", {
			innerHTML: "Resource Chart:",
			className: "ganttResourceHeader"
		}, this.ganttChart.content, "after");
		dojo.style(resourceHeader, "width", this.ganttChart.contentWidth + "px");
		var content = dojo.create("div", {className: "ganttResourceContent"}, resourceHeader, "after");
		dojo.style(content, {
			width: this.ganttChart.contentWidth + "px",
			height: (this.ganttChart.resourceChartHeight || (this.ganttChart.contentHeight * 0.8)) + "px"
		});
		this.content = content || this.content;
		//create Table
		this.reConstruct();
	},
	postAdjustment: function(){
		//contentData height
		this.contentData.firstChild.style.height = (this.ownerItem.length * 23) + "px";
		this.panelNames.firstChild.style.height = (this.ownerItem.length * 23) + "px";
	},
	
	refreshOwnerEntry: function(owner){
		this.refreshOwnerItem(owner);
		dojo.forEach(this.resourceInfo[owner], function(task, i){
			var item = this.ownerTaskNodeMapping[owner].tasks[i][0];
			this.refreshDetailedTaskEntry(owner, item, task);
		}, this);
	},
	createOwnerEntry: function(owner){
		var containerOwner = this.contentData.firstChild;
		var previousOwner = this.ownerItem[this.ownerItem.length - 1];
		this.ownerTaskNodeMapping[owner] = {};
		this.ownerTaskNodeMapping[owner][owner] = [];
		//create nodes
		var pos = dojo.position(containerOwner);
		//creation arrTasks
		var posY = (previousOwner ? parseInt(previousOwner.style.top) : (6 - 23)) + this.ganttChart.heightTaskItem + 11;
		//creation task item
		var oItem = this.createOwnerItem(owner, posY);
		containerOwner.appendChild(oItem);
		this.ownerItem.push(oItem);
		this.ownerTaskNodeMapping[owner][owner].push(oItem);
		if(this.panelNames){
			var oNameItem = this.createOwnerNameItem(owner, posY);
			this.panelNames.firstChild.appendChild(oNameItem);
			this.ownerNameItem.push(oNameItem);
			this.ownerTaskNodeMapping[owner][owner].push(oNameItem);
		}
		var currentOwnerNode = this.ownerItem[this.ownerNameItem.length - 1];
		var currentOwnerNameNode = this.ownerNameItem[this.ownerNameItem.length - 1];
		//adjust nodes
		if(this.panelNames){
			this.checkWidthTaskNameItem(currentOwnerNameNode);
			var treeImg = this.createTreeImg(currentOwnerNameNode);
			this.panelNames.firstChild.appendChild(treeImg);
			this.ownerTaskNodeMapping[owner][owner].push(treeImg);
		}
		this.ownerTaskNodeMapping[owner]["taskCount"] = this.resourceInfo[owner].length;
		this.ownerTaskNodeMapping[owner]["isOpen"] = false;
		this.ownerTaskNodeMapping[owner]["tasks"] = [];
		dojo.forEach(this.resourceInfo[owner], function(task){
			this.ownerTaskNodeMapping[owner]["tasks"].push(this.createDetailedTaskEntry(owner, currentOwnerNameNode, task));
		}, this);
		return this;
	},
	createOwnerNameItem: function(owner, posY){
		var ownerName = dojo.create("div", {
			id: owner,
			title: owner,
			innerHTML: owner,
			className: "ganttOwnerNameItem"
		});
		dojo.style(ownerName, "top", posY + "px");
		return ownerName;
	},
	refreshOwnerItem: function(owner){
		var item = this.ownerTaskNodeMapping[owner][owner][0];
		var start = this.ownerTimeConsume[owner].min, end = this.ownerTimeConsume[owner].max, dur = this.ownerTimeConsume[owner].dur;
		var posX = this.ganttChart.getPosOnDate(start); // should be task start date
		item.style.left = posX + "px";
		item.style.width = dur * this.ganttChart.pixelsPerWorkHour + "px";
		dojo.forEach(this.resourceInfo[owner], function(task, i){
			var tposX = this.ganttChart.getPosOnDate(task.taskItem.startTime); // should be task start date
			dojo.style(item.childNodes[i], {
				left: (tposX - posX) + "px",
				width: task.taskItem.duration * this.ganttChart.pixelsPerWorkHour + "px"
			});
		}, this);
	},
	createOwnerItem: function(owner, posY){
		var start = this.ownerTimeConsume[owner].min, end = this.ownerTimeConsume[owner].max, dur = this.ownerTimeConsume[owner].dur;
		var posX = this.ganttChart.getPosOnDate(start); // should be task start date
		var ownerControl = dojo.create("div", {
			id: owner,
			owner: true,
			className: "ganttOwnerBar"
		});
		dojo.style(ownerControl, {
			left: posX + "px",
			top: posY + "px",
			width: dur * this.ganttChart.pixelsPerWorkHour + "px",
			height: this.ganttChart.heightTaskItem + "px"
		});
		dojo.forEach(this.resourceInfo[owner], function(task){
			var ownerTaskItem = dojo.create("div", {
				id: owner,
				className: "ganttOwnerTaskBar"
			}, ownerControl);
			var tposX = this.ganttChart.getPosOnDate(task.taskItem.startTime); // should be task start date
			dojo.style(ownerTaskItem, {
				left: (tposX - posX) + "px",
				width: task.taskItem.duration * this.ganttChart.pixelsPerWorkHour + "px", // should be task duration
				height: this.ganttChart.heightTaskItem + "px"
			});
		}, this);
		return ownerControl;
	},
	refreshDetailedTaskEntry: function(owner, item, task){
		this.refreshTaskItem(item, task);
	},
	createDetailedTaskEntry: function(owner, parentNode, task){
		var taskItems = [];
		var containerTasks = this.contentData.firstChild;
		var posY = parseInt(parentNode.style.top);
		
		//creation task item
		var taskItem = this.createTaskItem(task, posY);
		taskItem.style.display = "none";
		containerTasks.appendChild(taskItem);
		this.ownerItem.push(taskItem);
		taskItems.push(taskItem);
		if(this.panelNames){
			var taskNameItem = this.createTaskNameItem(task.taskItem.name, posY);
			this.panelNames.firstChild.appendChild(taskNameItem);
			taskNameItem.style.display = "none";
			this.ownerNameItem.push(taskNameItem);
			taskItems.push(taskNameItem);
		}
		if(this.panelNames){
			this.ownerNameItem[this.ownerNameItem.length - 1].style.left = dojo.style(parentNode, "left") + 15 + "px";
			var arrConnectingLinesNames = this.createConnectingLinesPN(parentNode, this.ownerNameItem[this.ownerNameItem.length - 1]);
			dojo.forEach(arrConnectingLinesNames, function(lineName){
				lineName.style.display = "none";
			}, this);
			taskItems.push({
				"v": arrConnectingLinesNames[0],
				"h": arrConnectingLinesNames[1]
			});
			this.checkWidthTaskNameItem(this.ownerNameItem[this.ownerNameItem.length - 1]);
		}
		return taskItems;
	},
	createTaskNameItem: function(owner, posY){
		var taskNameItem = dojo.create("div", {
			id: owner,
			className: "ganttTaskNameItem",
			title: owner,
			innerHTML: owner
		});
		dojo.style(taskNameItem, "top", posY + "px");
		return taskNameItem;
	},
	refreshTaskItem: function(item, task){
		var posX = this.ganttChart.getPosOnDate(task.taskItem.startTime); // should be task start date
		dojo.style(item, {
			left: posX + "px",
			width: task.taskItem.duration * this.ganttChart.pixelsPerWorkHour + "px"
		});
	},
	createTaskItem: function(task, posY){
		var posX = this.ganttChart.getPosOnDate(task.taskItem.startTime); // should be task start date
		var itemControl = dojo.create("div", {
			id: task.taskItem.name,
			className: "ganttTaskBar"
		});
		dojo.style(itemControl, {
			left: posX + "px",
			top: posY + "px",
			width: task.taskItem.duration * this.ganttChart.pixelsPerWorkHour + "px",
			height: this.ganttChart.heightTaskItem + "px"
		});
		return itemControl;
	},
	createConnectingLinesPN: function(parentNode, currentNode){
		var arrConnectingLinesNames = [];
		var lineVerticalLeft = dojo.create("div", {
			innerHTML: "&nbsp;",
			className: "ganttResourceLineVerticalLeft"
		}, this.panelNames.firstChild);
		lineVerticalLeft.cNode = currentNode;
		lineVerticalLeft.pNode = parentNode;
		var LineHorizontalLeft = dojo.create("div", {
			noShade: true,
			color: "#000000",
			className: "ganttResourceLineHorizontalLeft"
		}, this.panelNames.firstChild);
		LineHorizontalLeft.cNode = currentNode;
		LineHorizontalLeft.pNode = parentNode;
		this.panelNames.firstChild.appendChild(LineHorizontalLeft);
		arrConnectingLinesNames.push(lineVerticalLeft);
		arrConnectingLinesNames.push(LineHorizontalLeft);
		return arrConnectingLinesNames;
	},
	createTreeImg: function(ownerNameItem){
		var treeImg = dojo.create("div", {
			id: ownerNameItem.id,
			className: "ganttImageTreeExpand"
		});
		dojo.attr(treeImg, "tabIndex", 0);
		var currentItem = this.ownerTaskNodeMapping[ownerNameItem.id];
		dojo.forEach(["onclick", "onkeydown"], function(e){
			this.ganttChart._events.push(
				dojo.connect(treeImg, e, this, function(evt){
					if(e == "onkeydown" && evt.keyCode != dojo.keys.ENTER){ return; }
					if(currentItem.isOpen){
						dojo.removeClass(treeImg, "ganttImageTreeCollapse");
						dojo.addClass(treeImg, "ganttImageTreeExpand");
						currentItem.isOpen = false;
						//collapse
						var reachTarget = false;
						for(var owner in this.ownerTaskNodeMapping){
							var ownerItem = this.ownerTaskNodeMapping[owner];
							if(reachTarget){
								dojo.forEach(ownerItem[owner], function(tItem){
									dojo.style(tItem, "top", dojo.style(tItem, "top") - currentItem.taskCount * 23 + "px");
								}, this);
								dojo.forEach(ownerItem.tasks, function(tItems){
									dojo.forEach(tItems, function(tItem){
										var item = !tItem.v && !tItem.h ? [tItem] : [tItem.v, tItem.h];
										dojo.forEach(item, function(t){
											dojo.style(t, "top", dojo.style(t, "top") - currentItem.taskCount * 23 + "px");
										}, this);
									}, this);
								}, this);
							}else{
								if(owner == ownerNameItem.id){
									reachTarget = true;
									dojo.forEach(ownerItem.tasks, function(tItems, i){
										dojo.forEach(tItems, function(tItem){
											this.styleOwnerItem(tItem, ownerItem[owner][0], "none", 0);
										}, this);
									}, this);
								}
							}
						}
					}else{
						dojo.removeClass(treeImg, "ganttImageTreeExpand");
						dojo.addClass(treeImg, "ganttImageTreeCollapse");
						currentItem.isOpen = true;
						//expand
						var reachTarget = false;
						for(var owner in this.ownerTaskNodeMapping){
							var ownerItem = this.ownerTaskNodeMapping[owner];
							if(reachTarget){
								dojo.forEach(ownerItem[owner], function(tItem){
									dojo.style(tItem, "top", dojo.style(tItem, "top") + currentItem.taskCount * 23 + "px");
								}, this);
								dojo.forEach(ownerItem.tasks, function(tItems){
									dojo.forEach(tItems, function(tItem){
										var item = !tItem.v && !tItem.h ? [tItem] : [tItem.v, tItem.h];
										dojo.forEach(item, function(t){
											dojo.style(t, "top", dojo.style(t, "top") + currentItem.taskCount * 23 + "px");
										}, this);
									}, this);
								}, this);
							}else{
								if(owner == ownerNameItem.id){
									reachTarget = true;
									dojo.forEach(ownerItem.tasks, function(tItems, i){
										dojo.forEach(tItems, function(tItem){
											this.styleOwnerItem(tItem, ownerItem[owner][0], "inline", (i + 1) * 23);
										}, this);
									}, this);
								}
							}
						}
					}
				})
			);
		}, this);
		dojo.addClass(treeImg, "ganttResourceTreeImage");
		dojo.style(treeImg, {
			left: (dojo.style(ownerNameItem, "left") - 12) + "px",
			top: (dojo.style(ownerNameItem, "top") + 3) + "px"
		});
		return treeImg;
	},
	styleOwnerItem: function(tItem, owner, displayType, topOffset){
		if(tItem.v || tItem.h){
			dojo.style(tItem.v, {
				height: Math.max(1, (tItem.v.cNode.offsetTop - tItem.v.pNode.offsetTop)) + "px",
				top: (tItem.v.pNode.offsetTop + 5) + "px",
				left: (tItem.v.pNode.offsetLeft - 9) + "px",
				display: displayType
			});
			dojo.style(tItem.h, {
				width: Math.max(1, (tItem.h.cNode.offsetLeft - tItem.h.pNode.offsetLeft + 4)) + "px",
				top: (tItem.h.cNode.offsetTop + 5) + "px",
				left: (tItem.h.pNode.offsetLeft - 9) + "px",
				display: displayType
			});
		}else{
			dojo.style(tItem, {
				display: displayType,
				top: parseInt(owner.style.top) + topOffset + "px"
			});
		}
	},
	checkWidthTaskNameItem: function(taskNameItem){
		if(taskNameItem && taskNameItem.offsetWidth + taskNameItem.offsetLeft > this.ganttChart.maxWidthPanelNames){
			var width = taskNameItem.offsetWidth + taskNameItem.offsetLeft - this.ganttChart.maxWidthPanelNames;
			var countChar = Math.round(width / (taskNameItem.offsetWidth / taskNameItem.firstChild.length));
			var tName = taskNameItem.id.substring(0, taskNameItem.firstChild.length - countChar - 3);
			tName += "...";
			taskNameItem.innerHTML = tName;
		}
	},
	createPanelOwners: function(){
		var panelOwner = dojo.create("div", {
			className: "ganttOwnerPanel"
		});
		dojo.style(panelOwner, {
			height: (this.contentHeight - this.ganttChart.panelTimeHeight - this.ganttChart.scrollBarWidth) + "px"
		});
		return panelOwner;
	},
	createPanelNamesOwners: function(){
		var panelNameOwner = dojo.create("div", {
			innerHTML: "&nbsp;",
			className: "ganttResourcePanelNamesOwners"
		});
		dojo.style(panelNameOwner, {
			height: (this.contentHeight - this.ganttChart.panelTimeHeight - this.ganttChart.scrollBarWidth) + "px",
			width: this.ganttChart.maxWidthPanelNames + "px"
		});
		return panelNameOwner;
	}
});
