Ext.namespace('Zarafa.common.ui.grid');

/**
 * @class Zarafa.common.ui.grid.Renderers
 * Methods of this object can be used as renderers for grid panels, to render
 * cells in custom format according to data type
 * @singleton
 */
Zarafa.common.ui.grid.Renderers = {
	/**
	 * Render the cell as Importance
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	importance : function(value, p, record)
	{
		if (value >= 0) {
			p.css = Zarafa.core.mapi.Importance.getClassName(value);
		}

		// add extra css class for empty cell
		p.css += ' zarafa-grid-empty-cell';

		return '';
	},

	/**
	 * Render the cell as Icon
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	icon : function(value, p, record)
	{
		p.css = Zarafa.common.ui.IconClass.getIconClass(record);

		// add extra css class for empty cell
		p.css += ' zarafa-grid-empty-cell';

		return '';
	},

	/**
	 * Render the cell as Attachment
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	attachment : function(value, p, record)
	{
		if (Ext.isDefined(record) && record.get('hide_attachments') === true) {
			return '';
		}

		p.css = (value === true) ? 'icon_attachment' : 'icon_noattachment';

		// add extra css class for empty cell
		p.css += ' zarafa-grid-empty-cell';

		return '';
	},

	/**
	 * Render the cell as Recurrence
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	recurrence : function(value, p, record)
	{
		p.css = value ? 'icon_recurring' : 'zarafa-grid-empty-cell';
		return '';
	},

	/**
	 * Renderer for reminder column
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	reminder : function (value, p, record)
	{
		p.css = value ? 'icon_reminder' : 'zarafa-grid-empty-cell';
		if (Ext.isDefined(record) && !Ext.isEmpty(record.get('reminder_time'))) {
			var reminderTime = record.get('reminder_time');
			var tooltip = String.format(_('Reminder is set on: {0}, {1}'), reminderTime.format(_('d-m-Y')), reminderTime.format(_('G:i')));
			p.attr = 'ext:qtip=\"'+Ext.util.Format.htmlEncode(tooltip)+'\"';
		}
		return '';
	},

	/**
	 * Renders the cell as categories view
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	categories : function(value, p, record)
	{
		// Render the categories
		var categories = Zarafa.common.categories.Util.getCategories(record);
		return Zarafa.common.categories.Util.getCategoriesHtml(categories);
	},

	/**
	 * Render the cell as Name
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	name : function(value, p, record)
	{
		p.css = 'mail_from';

		if(Ext.isEmpty(value)) {
			// if value is empty then add extra css class for empty cell
			p.css += ' zarafa-grid-empty-cell';
		}

		return Ext.util.Format.htmlEncode(value);
	},

	/**
	 * Render the cell as Display Name with presence status
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	displayName : function(value, p, record)
	{
		var user = Zarafa.core.data.UserIdObjectFactory.createFromRecord(record);
		var presenceStatus = Zarafa.core.PresenceManager.getPresenceStatusForUser(user);

		return '<span class="zarafa-presence-status '+Zarafa.core.data.PresenceStatus.getCssClass(presenceStatus)+'">' +
				'<span class="zarafa-presence-status-icon"></span>' +
				Zarafa.common.ui.grid.Renderers.name(value, p, record) +
				'</span>';
	},

	/**
	 * Render the cell as Sender
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	sender : function(value, p, record)
	{
		var userRecord = false;
		var presenceStatus = Zarafa.core.data.PresenceStatus.UNKNOWN;
		// Check which of the 2 properties must be used
		// FIXME: sent representing seems to be always set...
		value = record.get('sent_representing_name');
		if ( Ext.isEmpty(value) && Ext.isFunction(Ext.isFunction(record.getSender))) {
			value = record.get('sender_name');
			userRecord = record.getSender();
		} else if (Ext.isFunction(record.getSentRepresenting)) {
			userRecord = record.getSentRepresenting();
		}

		if (userRecord !== false) {
			var user = Zarafa.core.data.UserIdObjectFactory.createFromRecord(userRecord);
			presenceStatus = Zarafa.core.PresenceManager.getPresenceStatusForUser(user);
		}

		return '<span class="zarafa-presence-status '+Zarafa.core.data.PresenceStatus.getCssClass(presenceStatus)+'">' +
					'<span class="zarafa-presence-status-icon"></span>' +
					Zarafa.common.ui.grid.Renderers.name(value, p, record) +
				'</span>';
	},

	/**
	 * Render the cell as Organizer
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	organizer : function(value, p, record)
	{
		// Only render the cell as non-empty if the
		// record is actually a meeting.
		if (Ext.isDefined(record.isMeeting) && record.isMeeting()) {
			return Zarafa.common.ui.grid.Renderers.sender(value, p, record);
		} else {
			// if value is empty then add extra css class for empty cell
			p.css += ' zarafa-grid-empty-cell';
			return '';
		}
	},

	/**
	 * Render the cell as Subject
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	subject : function(value, p, record)
	{
		p.css = 'mail_subject';

		if(Ext.isEmpty(value)) {
			// if value is empty then add extra css class for empty cell
			p.css += ' zarafa-grid-empty-cell';
		}

		return Ext.util.Format.htmlEncode(value);
	},

	/**
	 * Render the cell as text view
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	text : function(value, p, record)
	{
		if(Ext.isEmpty(value)) {
			// if value is empty then add extra css class for empty cell
			p.css = 'zarafa-grid-empty-cell';
		}

		return Ext.util.Format.htmlEncode(value);
	},

	/**
	 * Render the cell as the recipient list.
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	to : function(value, p, record)
	{
		p.css = 'mail_to';

		if(Ext.isEmpty(value)) {
			// if value is empty then add extra css class for empty cell
			p.css += ' zarafa-grid-empty-cell';
		}

		return Ext.util.Format.htmlEncode(value);
	},

	/**
	 * Render the cell as the message size
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	size : function(value, p, record)
	{
		p.css = 'mail_size';

		if(Ext.isEmpty(value)) {
			// if value is empty then add extra css class for empty cell
			p.css += ' zarafa-grid-empty-cell';
		}

		return Ext.util.Format.fileSize(value);
	},

	/**
	 * Renderer for percentage column
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	percentage : function (value, p, record)
	{
		p.css = 'task_percentage';
		if ( isNaN(value) ){
			// 'value' will not be available as there is no 'complete' property while
			// rendering this column for mail record, using 'flag_status' instead.
			if ( record.get('flag_status') === Zarafa.core.mapi.FlagStatus.completed ) {
				return Ext.util.Format.percentage(1);
			}
			return '';
		}
		return Ext.util.Format.percentage(value);
	},

	/**
	 * Render the cell as Date (l d/m/y) string
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 *
	 * @return {String} The formatted string
	 */
	date : function(value, p)
	{
		p.css = 'mail_date';

		if ( !Ext.isDate(value) ){
			return _('None');
		}

		if ( container.getSettingsModel().get('zarafa/v1/main/datetime_display_format') === 'short' ){
			return value.getNiceFormat(false);
		} else {
			return value.format(_('l d/m/Y'));
		}
	},

	/**
	 * Render the cell as Date (l d/m/y) string, where the Date is should be represented in UTC
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata

	 * @return {String} The formatted string
	 */
	utcdate : function(value, p)
	{
		if ( Ext.isDate(value) ){
			value = value.toUTC();
		}

		return this.date(value, p);
	},

	/**
	 * Render the cell as date with time (l d/m/Y G:i) when the user has set the long display format
	 * or the 'nice' date when the the short display format has been set.
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @param {Integer} row The row in the grid for which a cell is rendered
	 * @param {Integer} column The column in the grid for which a cell is rendered
	 * @param {Zarafa.mail.MailStore} The store of the grid that is being rendered
	 * @param {Object} meta An object with meta data that can be used by the renderer function
	 *
	 * @return {String} The formatted string
	 */
	datetime : function(value, p, record, row, column, store, meta)
	{
		p.css = 'mail_date';

		if ( meta && meta.css ){
			p.css += ' ' + meta.css;
		}

		if ( !Ext.isDate(value) ){
			return _('None');
		}

		if ( container.getSettingsModel().get('zarafa/v1/main/datetime_display_format') === 'short' ){
			// Add one class that the tooltip can use to recognize a 'nice' date.
			// Add one class so the tooltip can easily get the timestamp of the date.
			p.css += ' k-date-nice k-ts-'+value.getTime();

			return value.getNiceFormat();
		} else {
			return value.format(_('l d/m/Y G:i'));
		}
	},

	/**
	 * Render the cell as date with time (l d/m/Y G:i when the user has set the Long display
	 * format, or d-m-Y, G:i when the short format has been set) This renderer should be used
	 * instead of {#datetime} when a time should always be shown, e.g. for the reminder time.
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 *
	 * @return {String} The formatted string
	 */
	dateWithTime : function(value, p)
	{
		p.css = '';

		if ( !Ext.isDate(value) ){
			return _('None');
		}

		if ( container.getSettingsModel().get('zarafa/v1/main/datetime_display_format') === 'short' ){
			// Add one class that the tooltip can use to recognize a 'nice' date.
			// Add one class so the tooltip can easily get the timestamp of the date.
			p.css += ' k-date-nice k-ts-'+value.getTime();
			return value.format(_('d-m-Y G:i'));
		} else {
			return value.format(_('l d/m/Y G:i'));
		}
	},

	/**
	 * Render the duration field
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	duration : function(value, p, record)
	{
		p.css = 'mail_duration';

		return value ? Ext.util.Format.duration(value, 1) : '';
	},

	/**
	 * Render the duration field by only using the hours annotation.
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	durationHours : function(value, p, record)
	{
		p.css = 'mail_duration';
		if ( !Ext.isDefined(value) ){
			return '';
		}

		return String.format(ngettext('{0} hour', '{0} hours', value), value);
	},

	/**
	 * Render the folder field (converts entryid into foldername).
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	folder : function(value, p, record)
	{
		var folder = container.getHierarchyStore().getFolder(value);
		if (folder) {
			return folder.get('display_name');
		} else {
			return _('Unknown');
		}
	},

	/**
	 * Render the Busy status.
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	busystatus : function(value, p, record)
	{
		return Zarafa.core.mapi.BusyStatus.getDisplayName(value);
	},

	/**
	 * Render the Appointment label.
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	label : function(value, p, record)
	{
		return Zarafa.core.mapi.AppointmentLabels.getDisplayName(value);
	},

	/**
	 * Render the Sensitivity.
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	sensitivity : function(value, p, record)
	{
		return Zarafa.core.mapi.Sensitivity.getDisplayName(value);
	},

	/**
	 * Render the Meeting status.
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	meetingstatus : function(value, p, record)
	{
		return Zarafa.core.mapi.MeetingStatus.getDisplayName(value);
	},

	/**
	 * Render the Recipient Type.
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	recipienttype : function(value, p, record)
	{
		switch (value) {
			case Zarafa.core.mapi.RecipientType.MAPI_TO:
			case Zarafa.core.mapi.RecipientType.MAPI_ORIG:
				if(record.isMeetingOrganizer()) {
					return _('Meeting Organizer');
				}
				return _('Required Attendee');
			case Zarafa.core.mapi.RecipientType.MAPI_BCC:
				return _('Resource');
			case Zarafa.core.mapi.RecipientType.MAPI_CC:
			/* falls through */
			default:
				return _('Optional Attendee');
		}
	},

	/**
	 * Render the Response Status.
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	responsestatus : function(value, p, record)
	{
		return Zarafa.core.mapi.ResponseStatus.getDisplayName(value);
	},

	/**
	 * Render the Follow-up Flag Status.
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	flag : function(value, p, record)
	{
		var flagStatus = record.get('flag_status');

		// add extra css class for empty cell
		p.css += 'zarafa-grid-empty-cell';

		if ( flagStatus === Zarafa.core.mapi.FlagStatus.completed ){
			p.css += ' icon_flag_complete';
			return '';
		}

		if ( !record.isMessageClass('IPM.Task') && flagStatus!==Zarafa.core.mapi.FlagStatus.flagged ){
			p.css += ' icon_flag';
			return '<div class="k-followup-flag"></div>';
		}

		// Now find the color we must show
		var dueDate = record.get('duedate');

		if ( !dueDate ){
			p.css += ' icon_flag_red';
			return '';
		}

		// Since we are interested in days and not in the exact time,
		// we will set all times to 12am so it will be easy to compare days
		dueDate.setToNoon();
		var dueDateTimestamp = dueDate.getTime();
		var today = new Date().setToNoon();
		var todayTimestamp = today.getTime();

		// If the due date is today or before today we will show a red flag
		if ( dueDateTimestamp <= todayTimestamp ){
			p.css += ' icon_flag_red';
			return '';
		}

		// If the due date is tomorrow (timestamp difference will be 24 hours),
		// we will show a dark orange flag
		if ( dueDateTimestamp-todayTimestamp === 24*60*60*1000 ){
			p.css += ' icon_flag_orange_dark';
			return '';
		}

		if ( dueDate.inSameWeekAs(today) ){
			p.css += ' icon_flag_orange';
			return '';
		}

		if ( today.inNextWeek(dueDate) ){
			p.css += ' icon_flag_yellow';
			return '';
		}

		p.css += ' icon_flag_red';
		return '';
	},

	/**
	 * Render the dueby field
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	dueBy : function(value, p, record)
	{
		var result = '';

		/*
		 * this one is really ugly hack appointments use reminder_time property to show due by time
		 * and task uses task_duedate property
		 */
		if (Zarafa.core.MessageClass.isClass(record.get('message_class'), 'IPM.Task', true)) {
			value = record.get('task_duedate');
		}

		if (!Ext.isDate(value)) {
			// if somehow no reminder_time/task_duedate property is present then we can't do anything here
			// because showing data from flagdueby property will not be good as it will contain
			// incorrect value
			return result;
		}

		var time1 = value.getTime();
		var time2 = new Date().getTime();

		// get diff in minutes
		var diff = Math.floor(Math.abs(time1 - time2)/60000);

		if(diff === 0) { // Now
			return _('Now');
		} else {
			result = Ext.util.Format.duration(diff);
		}

		if (time1 - time2 < 0){
			return String.format(_('{0} overdue'), result);
		}

		return result;
	},

	/**
	 * Render the Task Status.
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	taskstatus : function(value, p, record)
	{
		return Zarafa.core.mapi.TaskStatus.getDisplayName(value);
	},

	/**
	 * Render the Colors in textual format.
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	colorTextValue : function(value, p, record)
	{
		return Zarafa.core.mapi.NoteColor.getColorText(value);
	},

	/**
	 * Render the name, subject and body information of record
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	dataColumn : function(value, p, record)
	{
		p.css = 'search-data';

		if(Ext.isEmpty(value)) {
			// if value is empty then add extra css class for empty cell
			p.css += ' zarafa-grid-empty-cell';
		}

		var messageClass = record.get('message_class');
		//TODO: give these variables better names
		var name = '';
		var subject = '';
		var body = '';

		switch (messageClass) {
			case 'IPM.Contact':
			case 'IPM.DistList':
				name = Ext.util.Format.htmlEncode(record.get('display_name'));
				subject = Ext.util.Format.htmlEncode(record.get('fileas'));
				//TODO: try to get an emailadress from other fields if this field is empty
				body = Ext.util.Format.htmlEncode(record.get('email_address_1'));
				break;
			case 'IPM.Task':
				name = Ext.util.Format.htmlEncode(record.get('subject'));
				body = Ext.util.Format.htmlEncode(record.get('body'));
				break;
			case 'IPM.StickyNote':
				name = Ext.util.Format.htmlEncode(record.get('subject'));
				subject = Ext.util.Format.htmlEncode(record.get('body'));
				break;
			default:
			//case 'IPM.Note':
			//case 'IPM.Appointment':
			//case 'IPM.Schedule':
				name = Zarafa.common.ui.grid.Renderers.sender(value, p, record);
				subject = Ext.util.Format.htmlEncode(record.get('subject'));
				body = Ext.util.Format.htmlEncode(record.get('body'));
				break;
		}
		return ''+
			'<table cellpadding=0 cellspacing=0 style="width:100%" class="messageclass-data mc-'+messageClass.toLowerCase().replace('.', '')+'">' +
				'<tr>' +
					'<td class="x-grid3-col x-grid3-cell x-grid3-td-0 icon ' + Zarafa.common.ui.IconClass.getIconClass(record) + '"></td>' +
					'<td class="name"><div class="padding">' + name + '</div></td>' +
					'<td class="subject-body"><div class="padding">' + ( subject ? '<span class="subject">'+subject+'</span>' : '' ) + ( body ? '<span class="body">'+body+'</span>' : '' ) + '</div></td>' +
				'</tr>' +
			'</table>';
	},

	/**
	 * Render the date field and attachment icon if record contains attachment.
	 *
	 * @param {Object} value The data value for the cell.
	 * @param {Object} p An object with metadata
	 * @param {Ext.data.record} record The {Ext.data.Record} from which the data was extracted.
	 * @return {String} The formatted string
	 */
	dateColumn : function(value, p, record)
	{
		p.css = 'search-date';

		// # TRANSLATORS: See http://docs.sencha.com/ext-js/3-4/#!/api/Date for the meaning of these formatting instructions
		var date = Ext.isDate(value) ? value.format(_('d/m/Y')) : '';

		// TODO: make insertionpoint for other icons (reuse mail grid insertionpoint???)
		return '<table cellpadding=0 cellspacing=0 style="width:100%"><tr>' +
					'<td class="date"><div>' + date + '</div></td>' +
					( record.get('hasattach') ? '<td class="icon_attachment" style="width:22px"></td>' : '' ) +
				'</tr></table>';
	}
};