// Copyright 2008 ProjectWizards GmbH. All rights reserved.

//console.log("GanttRulerRow.js");

var GanttRulerRow = Base.extend({
	constructor: function (ruler, environment)
	{
		this.environment = environment;
		this.ruler = ruler;
		this.lastStyleForUnit = {};
		this.style = 0;
		this.unit = eDurationUnit.MEDay;
	},

	setStyle: function(style)
	{
		this.style = style;	
	},

	setUnit: function(unit)
	{
		var changed = this.unit!=unit;
		this.unit = unit;
		this.ruler.setPrimaryUnit(this.ruler.primaryRow().unit);
		if(changed){
			var lastStyle = this.lastStyleForUnit[unit];
			if(lastStyle)
				this.setStyle(lastStyle);
			else
				this.setStyle(this.defaultStyle());
		}
		var nextRow = this.nextRow();
		if(nextRow && (nextRow.unit < unit)){
			nextRow.setUnit(this.oneUnitBiggerThanUnit(unit));	
			nextRow.setStyle(this.defaultStyle());
		}	
		if(this.isPrimary() && changed){
			this.ruler.updatePixelsPerDay();
		}
		this.ruler.updateModificationDate();	
	},

	defaultStyle: function()
	{
		var style = 0;
		var order = this.order();
		var numRows = this.ruler.rows.length;
		var unit = this.unit;
		var isFirst = order==0;
		var isLast = order==numRows-1;
		if(unit == eDurationUnit.MEYears){
			style = 0;		
		}else if(unit == eDurationUnit.MEQuarterYears){
			if(!isLast)
				style = 0;
			else
				style = 1;
		}else if(unit == eDurationUnit.MEMonths){
			if(isFirst && !isLast)
				style = 0;
			else if(isLast)
				style = 4;
			else 
				style = 2;
		}	else if(unit == eDurationUnit.MECalendarWeeks){
			if(isLast)
				style = 5;
			else
				style = 2;
		}else if(unit == eDurationUnit.MEDays){
			if(!isFirst)
				style = 5;
			else
				style = 0;
		}else if(unit == eDurationUnit.MEHours){
			if(isLast)
				style = 3;
			else
				style = 0;
		}else if(unit == eDurationUnit.MEMinutes)
			style = 0;
		return style;		
	},

	order: function()
	{
		return this.ruler.rows.indexOf(this);
	},


	isPrimary: function()
	{
		return this.order()==0;
	},

	reverseOrder: function()
	{
		var rows = this.ruler.rows;
		return rows.length-rows.indexOf(self)-1;
	},

	setRuler: function(ruler)
	{
		this.ruler = ruler;
	},

	numberOfStyles: function()
	{
		switch(this.unit){
			case eDurationUnit.MEMinutes:
				return 8;
			case eDurationUnit.MEHours:
				return this.environment.format.systemTimeFormatUses12Hours ? 14 : 13;
			case eDurationUnit.MEDays:
				return 15;
			case eDurationUnit.MECalendarWeeks:
				return 17;
			case eDurationUnit.MEMonths:
				return 11;
			case eDurationUnit.MEQuarterYears:
				return 8;
			case eDurationUnit.MEYears:
			default:
				return 7;
		}
	},

	rowCode: function()
	{
		return this.ruler ? this.unit*1000 + this.style : 0;
	},

	possibleStylesNamesUsingLocale: function(locale)
	{
		var names = [];
		var projectStart = this.ruler.project.valueForKey('plannedStartDate');
		if(!projectStart)
			projectStart = new Date();
		var numStyles = this.numberOfStyles();
		var unit = this.unit;
		for(var style = 0; style<numStyles; style++){
			var description = this.descriptionForUnitStyleAtDateWithLocaleForMenu(unit, style, projectStart, locale, true);
			if(description)
				names.push(description);
		}
		return names;
	},

	mayRemove: function()
	{
		return this.ruler.mayRemoveARow();
	},

	mayAddBehind: function()
	{
		return this.ruler.mayAddARow();
	},

	maySwitchToUnit: function(unit)
	{
		var result = true;
		var previousRow = this.previousRow();
		if(previousRow)
			result = previousRow.unit <= unit;
		return result;
	},

	previousRow: function()
	{
		return this.order()>0 ? this.ruler.rows[order-1] : null;
	},

	nextRow: function()
	{
		var order = this.order();
		var rows = this.ruler.rows;
		return order<rows.length-1 ? rows[order+1] : null;
	},

	newRowBehind: function()
	{
		var unit = this.unit;
		var newUnit = eDurationUnit.MECalendarWeeks;
		if(unit == eDurationUnit.MEMinutes)
			newUnit = eDurationUnit.MEHours;
		else if(unit == eDurationUnit.MEHours)
			newUnit = eDurationUnit.MEDays;
		else if(unit == eDurationUnit.MEDays)
			newUnit = eDurationUnit.MECalendarWeeks;
		else if(unit == eDurationUnit.MECalendarWeeks)
			newUnit = eDurationUnit.MEMonths;
		else if(unit == eDurationUnit.MEMonths)
			newUnit = eDurationUnit.MEQuarterYears;
		else if(unit == eDurationUnit.MEQuarterYears)
			newUnit = eDurationUnit.MEYears;
		return this.ruler.addRowWithUnitStyleWithOrder(newUnit,0,this.order()+1);
	},

	keyForRelativeUnit: function(unit)
	{
		switch(unit){
			case eDurationUnit.MEMinutes:
				return "Minute";
			case eDurationUnit.MEHours:
				return "Hour";
			default:
			case eDurationUnit.MEDays:
				return "Day";
			case eDurationUnit.MECalendarWeeks:
				return "Week";
			case eDurationUnit.MEMonths:
				return "Month";
			case eDurationUnit.MEQuarterYears:
				return "QuarterYear";
			case eDurationUnit.MEYears:
				return "Year";
		}
	},

	descriptionAtDateWithLocale: function(date,locale)
	{
		return this.descriptionForUnitStyleAtDateWithLocaleForMenu(this.unit, this.style, date, locale, false);
	},

	startOfUnitContainingDateClipAtDate: function(date, clipDate)
	{
		return this.ruler.startOfUnitContainingDateClipAtDateExtendIfTooThin(this.unit, date, clipDate, true);
	},

	endOfUnitWithStartDateClipAtDate: function(date, clipDate)
	{
		return this.ruler.endOfUnitWithStartDateClipAtDateExtendIfTooThin(this.unit, date, clipDate, true);
	},

	dictionaryRepresentation: function()
	{
		var dict = {};
		dict["unit"] = this.unit;
		dict["style"] = this.style;	
		return dict;
	},

	descriptionForRelativeUnitShortnessAtDateFromEndWithLocaleForMenu: function(unit,shortness,date,fromEnd,locale,forMenu)
	{
		var unitStartEndDate = null;
		var projectUnitStartEndDate = null;
		if(fromEnd){
			var projectEndDate = this.ruler.project.valueForKey('plannedEndDate');
			if(!projectEndDate)
				projectEndDate = new Date();
			projectUnitStartEndDate = this.ruler.endOfUnitContainingDateClipAtDateExtendIfTooThin(unit, projectEndDate, null, true);
			unitStartEndDate = this.ruler.endOfUnitWithStartDateClipAtDateExtendIfTooThin(unit, date, null, true);
		}else{
			var projectStartDate = this.ruler.project.valueForKey('plannedStartDate');
			if(!projectStartDate)
				projectStartDate = new Date();
			projectUnitStartEndDate = this.ruler.startOfUnitContainingDateClipAtDateExtendIfTooThin(unit, projectStartDate ? projectStartDate : date, null, true);
			unitStartEndDate = this.ruler.startOfUnitContainingDateClipAtDateExtendIfTooThin(unit, date, null, true);
		}
		var format;
		if(shortness==2)
			format = "%d";
		else{
			var unitKey = this.keyForRelativeUnit(unit);
			if(shortness==1){
				var key = unitKey + "Short";
				format = this.environment.localizedString(key) + "%d";
			}
			else
				format = this.environment.localizedString(unitKey) + " %d";
		}
		if(forMenu)
			format += " " + this.environment.localizedString(fromEnd ? "(From End)" : "(From Start)");
		var diff;
		switch(unit){
			case eDurationUnit.MEMinutes:
				diff = unitStartEndDate.timeIntervalSinceDate(projectUnitStartEndDate)/60; break;
			case eDurationUnit.MEHours:
				diff = unitStartEndDate.timeIntervalSinceDate(projectUnitStartEndDate)/3600; break;
			default:
			case eDurationUnit.MEDays:
				diff = unitStartEndDate.timeIntervalSinceDate(projectUnitStartEndDate)/(3600*24); break;
			case eDurationUnit.MECalendarWeeks:
				diff = unitStartEndDate.timeIntervalSinceDate(projectUnitStartEndDate)/(3600*24*7); break;
			case eDurationUnit.MEMonths:
				diff = Date.diff("m", projectUnitStartEndDate, unitStartEndDate, true); break;
			case eDurationUnit.MEQuarterYears:
				diff = Date.diff("m", projectUnitStartEndDate, unitStartEndDate, true)/3; break;
			case eDurationUnit.MEYears:
				diff = Date.diff("m", projectUnitStartEndDate, unitStartEndDate, true)/12; break;
		}

		if(fromEnd)
			diff = -diff;
		if(diff>=0)
			diff++;
		var result = stringWithFormat(format, diff);
		return result;
	},

	descriptionForUnitStyleAtDateWithLocaleForMenu: function(unit, style, date, locale, forMenu)
	{
		var result = null;
		if(unit==eDurationUnit.MEMinutes){
			if(style==0)
				return date.format("m", true);
			else if(style==1)
				result = ""+date.getUTCMinutes();
			else if(style==2 || style==3 || style==4)
				result = this.descriptionForRelativeUnitShortnessAtDateFromEndWithLocaleForMenu(unit, style-2, date, false, locale, forMenu);
			else if(style==5 || style==6 || style==7)
				result = this.descriptionForRelativeUnitShortnessAtDateFromEndWithLocaleForMenu(unit, style-5, date, true, locale, forMenu);
		}else if(unit==eDurationUnit.MEHours){
			if(style==0)
				result = date.format(this.environment.format.systemOnlyHourNumberTimeFormat, true);
			else if(style==1)
				result = date.format(this.environment.format.systemOnlyHourTimeFormat, true);
			else if(style==1)
				result = date.format(this.environment.format.systemTimeFormatFixedHours, true);
			else if(style==2)
				result = date.format(this.environment.format.systemShortDateFormat+" "+this.environment.format.systemOnlyHourTimeFormat, true);
			else if(style==3)
				result = date.format(this.environment.format.systemShortDateFormat+" "+this.environment.format.systemTimeFormatFixedHours, true);
			else if(style==4)
				result = date.format(this.environment.format.systemShortDateFormatWithWeekday+" "+this.environment.format.systemTimeFormatFixedHours, true);			
			else if(style==5)
				result = date.format(this.environment.format.systemDateFormatWithoutWeekday+" "+this.environment.format.systemTimeFormatFixedHours, true);			
			else if(style==6)
				result = date.format(this.environment.format.systemDateFormat+" "+this.environment.format.systemTimeFormatFixedHours, true);			
			else if(style==7 || style==8 || style==9)
				result = this.descriptionForRelativeUnitShortnessAtDateFromEndWithLocaleForMenu(unit, style-7, date, false, locale, forMenu);
			else if(style==10 || style==11 || style==12)
				result = this.descriptionForRelativeUnitShortnessAtDateFromEndWithLocaleForMenu(unit, style-10, date, true, locale, forMenu);		
		}else if(unit==eDurationUnit.MEDays){
			switch(style){
				default:
				case 0:
					result = date.format("d", true); break;
				case 1:
					result = date.format("E", true); break;			
				case 2:
					result = date.format("d (E)", true); break;			
				case 3:
					result = date.format(this.environment.format.systemShortDateFormatWithoutYear, true); break;			
				case 4:
					result = date.format(this.environment.format.systemShortDateFormat, true); break;			
				case 5:
					result = date.format(this.environment.format.systemShortDateFormatWithWeekday, true); break;			
				case 6:
					result = date.format(this.environment.format.systemDateFormatWithoutYearAndWeekday, true); break;			
				case 7:
					result = date.format(this.environment.format.systemDateFormatWithoutWeekday, true); break;			
				case 8:
					result = date.format(this.environment.format.systemDateFormat, true); break;			
				case 9:
				case 10:
				case 11:
					result = this.descriptionForRelativeUnitShortnessAtDateFromEndWithLocaleForMenu(unit, style-9, date, false, locale, forMenu); break;
				case 12:
				case 13:
				case 14:
					result = this.descriptionForRelativeUnitShortnessAtDateFromEndWithLocaleForMenu(unit, style-12, date, true, locale, forMenu); break;
			}
		}else if(unit==eDurationUnit.MECalendarWeeks){
			var week = date.getCalendarWeekUTC(this.environment);
			var weekStart = Date.startOfCalendarWeekInYear(week, date.getUTCFullYear(), true, this.environment);
			var dateRepresentingWeek = new Date(weekStart.getTime());
			dateRepresentingWeek.add("d", 3, true);	//ak false vor dem true entfernt
			var cwString = this.environment.calendarWeekString;		
			if(style==0)
				result = "" + cwString +" "+ week;
			else if(style==1)
				result = cwString + " " + week + " " + date.getUTCFullYear();
			else if(style==2)
				result = cwString + " " + week + ", " + weekStart.format(this.environment.format.systemShortDateFormatWithoutYear, true);
			else if(style==3)
				result = cwString + " " + week + ", " + weekStart.format(this.environment.format.systemShortDateFormat, true);
			else if(style==4)
				result = cwString + " " + week + ", " + weekStart.format(this.environment.format.systemDateFormatWithoutYearAndWeekday, true);
			else if(style==5)
				result = cwString + " " + week + ", " + dateRepresentingWeek.format("MMM yyyy", true);
			else if(style==6)
				result = cwString + " " + week + ", " + weekStart.format(this.environment.format.systemDateFormatWithoutWeekday, true);
			else if(style==7)
				result = weekStart.format(this.environment.format.systemShortDateFormatWithoutYear, true);
			else if(style==8)
				result = weekStart.format(this.environment.format.systemShortDateFormat, true);
			else if(style==9)
				result = weekStart.format(this.environment.format.systemDateFormatWithoutYearAndWeekday, true);
			else if(style==10)
				result = weekStart.format(this.environment.format.systemDateFormatWithoutWeekday, true);
			else if(style==11 || style==12 || style==13)
				result = this.descriptionForRelativeUnitShortnessAtDateFromEndWithLocaleForMenu(unit, style-11, date, false, locale, forMenu);
			else if(style==14 || style==15 || style==16)
				result = this.descriptionForRelativeUnitShortnessAtDateFromEndWithLocaleForMenu(unit, style-14, date, true, locale, forMenu);
			else if(style==17)
				result = "" + cwString +" "+ week + ", " + weekStart.format("dd");
			else if(style==18)
				result = "" + weekStart.format("dd");	
		}else if(unit==eDurationUnit.MEMonths){
			if(style==0)
				result = date.format("MM", true);
			else if(style==1)
				result = date.format("MM/yyyy", true);
			else if(style==2)
				result = date.format("MMM", true);
			else if(style==3)
				result = date.format("MMM yy", true);
			else if(style==4)
				result = date.format("MMM yyyy", true);
			else if(style==5 || style==6 || style==7)
				result = this.descriptionForRelativeUnitShortnessAtDateFromEndWithLocaleForMenu(unit, style-5, date, false, locale, forMenu);
			else if(style==8 || style==9 || style==10)
				result = this.descriptionForRelativeUnitShortnessAtDateFromEndWithLocaleForMenu(unit, style-8, date, true, locale, forMenu);
		}else if(unit==eDurationUnit.MEQuarterYears){
			var quarter = Math.floor((date.getUTCMonth()+3)/3);
			var quarterKey = "Q"+quarter;
			if(style==0)
				result = this.environment.localizedString(quarterKey);			
			else if(style==1)
				result = this.environment.localizedString(quarterKey) + " / " + date.getUTCFullYear();
			else if(style==2 || style==3 || style==4)
				result = this.descriptionForRelativeUnitShortnessAtDateFromEndWithLocaleForMenu(unit, style-2, date, false, locale, forMenu);
			else if(style==5 || style==6 || style==7)
				result = this.descriptionForRelativeUnitShortnessAtDateFromEndWithLocaleForMenu(unit, style-5, date, true, locale, forMenu);
		}else if(unit==eDurationUnit.MEYears){
			if(style==0)
				result = ""+date.getUTCFullYear();
			else if(style==1 || style==2 || style==3)
				result = this.descriptionForRelativeUnitShortnessAtDateFromEndWithLocaleForMenu(unit, style-1, date, false, locale, forMenu);
			else if(style==4 || style==5 || style==6)
				result = this.descriptionForRelativeUnitShortnessAtDateFromEndWithLocaleForMenu(unit, style-4, date, true, locale, forMenu);
		}
		return result;
	},
	
	unitStartDatesBetweenStartDateAndEndDate: function(start, end)
	{		
		result = [];
		if(start && end){
			var startDate = new Date(Math.max(start.getTime(), this.ruler.startDate.getTime()));
			var endDate = new Date(Math.min(end.getTime(), this.ruler.endDate.getTime()));			
			var unitStart = this.startOfUnitContainingDateClipAtDate(startDate, this.ruler.startDate);
			while(unitStart.getTime() < endDate.getTime()){
				result.push(unitStart);
				unitStart = this.endOfUnitWithStartDateClipAtDate(unitStart, this.ruler.endDate);
			}	
		}
		return result;
	}
	
	

},
	// Class Interface:
{
	rowFromDictionary: function(dict)
	{
		var row = new GanttRulerRow();
		row.setUnit(dict["unit"]);
		row.setStyle(dict["style"]);
		return row;
	},

	oneUnitBiggerThanUnit: function(unit)
	{
		if(unit == eDurationUnit.MEMinutes)
			return eDurationUnit.MEHours;
		else if(unit == eDurationUnit.MEHours)
			return eDurationUnit.MEDays;
		else if(unit == eDurationUnit.MEDays)
			return eDurationUnit.MECalendarWeeks;
		else if(unit == eDurationUnit.MECalendarWeeks)
			return eDurationUnit.MEMonths;
		else if(unit == eDurationUnit.MEMonths)
			return eDurationUnit.MEQuarterYears;
		else
			return eDurationUnit.MEYears;
	},

	oneUnitSmallerThanUnit: function(unit)
	{
		if(unit == eDurationUnit.MEYears)
			return eDurationUnit.MEQuarterYears;
		else if(unit == eDurationUnit.MEQuarterYears)
			return eDurationUnit.MEMonths;
		else if(unit == eDurationUnit.MEMonths)
			return eDurationUnit.MECalendarWeeks;
		else
			return eDurationUnit.MEDays;
	},

	oneUnitSmallerThanUnitIncludingTimes: function(unit)
	{
		if(unit == eDurationUnit.MEYears)
			return eDurationUnit.MEQuarterYears;
		else if(unit == eDurationUnit.MEQuarterYears)
			return eDurationUnit.MEMonths;
		else if(unit == eDurationUnit.MEMonths)
			return eDurationUnit.MECalendarWeeks;
		else if(unit == eDurationUnit.MECalendarWeeks)
			return eDurationUnit.MEDays;
		else if(unit == eDurationUnit.MEDays)
			return eDurationUnit.MEHours;
		else if(unit == eDurationUnit.MEHours)
			return eDurationUnit.MEMinutes;
		else
			return eDurationUnit.MESeconds;
	}
	

});
