/**
 * @constructor
 */
function CForgotView()
{
	this.gotoForgot = ko.observable(false);
	this.gotoForgot.subscribe(function () {
		this.visibleEmailForm(true);
		this.visibleQuestionForm(false);
		this.visiblePasswordForm(false);
	}, this);
	
	this.visibleEmailForm = ko.observable(true);
	this.email = ko.observable('');
	this.emailFocus = ko.observable(false);
	this.gettingQuestion = ko.observable(false);
	this.getQuestionButtonText = ko.computed(function () {
		return this.gettingQuestion() ? TextUtils.i18n('%MODULENAME%/ACTION_GET_QUESTION_IN_PROGRESS') : TextUtils.i18n('%MODULENAME%/ACTION_GET_QUESTION');
	}, this);
	this.allowGetQuestion = ko.computed(function () {
		return !this.gettingQuestion() && $.trim(this.email()) !== '';
	}, this);
	this.getQuestionCommand = Utils.createCommand(this, this.executeGetQuestion, this.allowGetQuestion);
	
	this.visibleQuestionForm = ko.observable(false);
	this.question = ko.observable('');
	this.answer = ko.observable('');
	this.answerFocus = ko.observable(false);
	this.validatingAnswer = ko.observable(false);
	this.validateAnswerButtonText = ko.computed(function () {
		return this.validatingAnswer() ? TextUtils.i18n('%MODULENAME%/ACTION_VALIDATE_ANSWER_IN_PROGRESS') : TextUtils.i18n('%MODULENAME%/ACTION_VALIDATE_ANSWER');
	}, this);
	this.allowValidatingAnswer = ko.computed(function () {
		return !this.validatingAnswer() && $.trim(this.answer()) !== '';
	}, this);
	this.validateAnswerCommand = Utils.createCommand(this, this.executeValidateAnswer, this.allowValidatingAnswer);
	
	this.visiblePasswordForm = ko.observable(false);
	this.password = ko.observable('');
	this.confirmPassword = ko.observable('');
	this.passwordFocus = ko.observable(false);
	this.confirmPasswordFocus = ko.observable(false);
	this.changingPassword = ko.observable(false);
	this.changePasswordButtonText = ko.computed(function () {
		return this.changingPassword() ? TextUtils.i18n('CORECLIENT/ACTION_RESET_PASSWORD_IN_PROGRESS') : TextUtils.i18n('CORECLIENT/ACTION_RESET_PASSWORD');
	}, this);
	this.allowChangePassword = ko.computed(function () {
		var
			sPassword = $.trim(this.password()),
			sConfirmPassword = $.trim(this.confirmPassword()),
			bEmptyFields = (sPassword === '' || sConfirmPassword === '')
		;

		return !this.changingPassword() && !bEmptyFields;
	}, this);
	this.changePasswordCommand = Utils.createCommand(this, this.executeChangePassword, this.allowChangePassword);
	
	App.broadcastEvent('%ModuleName%::ConstructView::after', {'Name': this.ViewConstructorName, 'View': this});
}
CFilesView.prototype.executeRename = function ()
{
	var
		oItem = _.first(this.selector.listCheckedAndSelected()),
		bSeparateExtension = Settings.EditFileNameWithoutExtension && oItem instanceof CFileModel,
			sName = bSeparateExtension ? Utils.getFileNameWithoutExtension(oItem.fileName()) : oItem.fileName(),
			sExtension = bSeparateExtension ? Utils.getFileExtension(oItem.fileName()) : ''
	;
	
	if (!this.bPublic && oItem)
	{
		Popups.showPopup(RenamePopup, [sName, _.bind(this.renameItem, this, sExtension)]);
	}
};
			}).on('keydown', function(oEvent, oItem) {
				if (aSourceResponseItems && oSelectedItem && !oSelectedItem.global && oEvent.keyCode === Enums.Key.Del && oEvent.shiftKey) //shift+del on suggestions list
				{
					Utils.calmEvent(oEvent);
					fDelete();
				}
			});
/**
 * @constructor for object that display buttons "PGP Sign/Encrypt" and "Undo PGP"
 */
function CComposeButtonsView()
{
	this.sId = 'OpenPgp';
	this.bAllowMobile = true;
	
	this.enableOpenPgp = Settings.enableOpenPgp;
	
	this.pgpSecured = ko.observable(false);
	this.pgpEncrypted = ko.observable(false);
	this.fromDrafts = ko.observable(false);
	
	this.disableHeadersEdit = this.pgpEncrypted;
	this.disableBodyEdit = this.pgpSecured;
	this.disableAutosave = this.pgpSecured;
	
	this.visibleDoPgpButton = ko.computed(function () {
		return this.enableOpenPgp() && (!this.pgpSecured() || this.pgpEncrypted() && this.fromDrafts());
	}, this);
	this.visibleUndoPgpButton = ko.computed(function () {
		return this.enableOpenPgp() && this.pgpSecured() && (!this.pgpEncrypted() || !this.fromDrafts());
	}, this);
	
	this.isEnableOpenPgpCommand = ko.computed(function () {
		return this.enableOpenPgp() && !this.pgpSecured();
	}, this);
	this.openPgpCommand = Utils.createCommand(this, this.confirmOpenPgp, this.isEnableOpenPgpCommand);
	
	this.bComposeModeChanged = false;
}
	$(document).on('keydown', $.proxy(function(ev) {
		var
			sKey = ev.keyCode,
			bComputed = ev && !ev.ctrlKey && !ev.altKey && !ev.shiftKey && !Utils.isTextFieldFocused() && this.shown(),
			oList = this.oMessageList,
			oFirstMessage = oList.collection()[0],
			bGotoSearch = oFirstMessage && MailCache.currentMessage() && oFirstMessage.uid() === MailCache.currentMessage().uid()
		;
		
		if (bComputed && sKey === Enums.Key.s || bComputed && bGotoSearch && sKey === Enums.Key.Up)
		{
			ev.preventDefault();
			this.searchFocus();
		}
		else if (oList.isFocused() && ev && sKey === Enums.Key.Down && oFirstMessage)
		{
			ev.preventDefault();
			oList.isFocused(false);
			oList.routeForMessage(oFirstMessage);
		}
		else if (bComputed && sKey === Enums.Key.n)
		{
			this.executeCompose();
			ev.preventDefault();
		}
	},this));
	$(document).on('keydown', _.bind(function(ev) {
		if (this.shown() && ev && ev.keyCode === Enums.Key.s && this.selector.useKeyboardKeys() && !Utils.isTextFieldFocused())
		{
			ev.preventDefault();
			this.isSearchFocused(true);
		}
	}, this));
CMailView.prototype.messagesDrop = function (oToFolder, oEvent, oUi)
{
	if (oToFolder)
	{
		var
			oHelper = oUi && oUi.helper ? oUi.helper : null,
			sFolder = oHelper ? oHelper.data('p7-message-list-folder') : '',
			aUids = oHelper ? oHelper.data('p7-message-list-uids') : null
		;

		if ('' !== sFolder && null !== aUids)
		{
			Utils.uiDropHelperAnim(oEvent, oUi);
			if(oEvent.ctrlKey)
			{
				this.oMessageList.executeCopyToFolder(oToFolder.fullName());
			}
			else
			{
				this.oMessageList.executeMoveToFolder(oToFolder.fullName());
			}
			
			this.uncheckMessages();
		}
	}
};
CFilesView.prototype.renameItem = function (sExtension, sNamePart)
{
	var
		sName = (sExtension === '') ? sNamePart : sNamePart + '.' + sExtension,
		oItem = _.first(this.selector.listCheckedAndSelected())
	;
	
	if (!Utils.validateFileOrFolderName(sName))
	{
		return oItem instanceof CFolderModel ?
			TextUtils.i18n('%MODULENAME%/ERROR_INVALID_FOLDER_NAME') : TextUtils.i18n('%MODULENAME%/ERROR_INVALID_FILE_NAME');
	}
	else
	{
		Ajax.send('Rename', {
				'Type': oItem.storageType(),
				'Path': oItem.path(),
				'Name': oItem.id() || oItem.fileName(),
				'NewName': sName,
				'IsLink': oItem.bIsLink ? 1 : 0,
				'IsFolder': oItem instanceof CFolderModel
			}, this.onRenameResponse, this
		);
	}
	
	return '';
};
CMailView.prototype.searchFocus = function ()
{
	if (this.oMessageList.selector.useKeyboardKeys() && !Utils.isTextFieldFocused())
	{
		this.oMessageList.isFocused(true);
	}
};
CDateModel.prototype.getDate = function ()
{
	var sFormat = 'ddd, MMM D, YYYY';
	
	if (UserSettings.UserSelectsDateFormat)
	{
		sFormat = 'ddd, ' + Utils.getDateFormatForMoment(UserSettings.dateFormat());
	}
	
	return (this.oMoment) ? this.oMoment.format(sFormat) : '';
};
/**
 * @constructor
 */ 
function CAccountFoldersPaneView()
{
	this.bAllowTemplateFolders = Settings.AllowTemplateFolders;
	
	this.highlighted = ko.observable(false).extend({'autoResetToFalse': 500});

	this.collection = ko.observableArray(MailCache.editedFolderList().collection());
	this.oCollSubscription = MailCache.editedFolderList().collection.subscribe(function (koCollection) {
		this.collection(koCollection);
	}, this);
	this.totalMessageCount = ko.observable(0);
	
	this.enableButtons = ko.computed(function () {
		return MailCache.editedFolderList().initialized();
	}, this);
	
	MailCache.editedFolderList.subscribe(function(oFolderList) {
		this.collection(oFolderList.collection());
		this.setTotalMessageCount();
		this.oCollSubscription.dispose();
		this.oCollSubscription = oFolderList.collection.subscribe(function (koCollection) {
			this.collection(koCollection);
		}, this);
	}, this);
	
	this.addNewFolderCommand = Utils.createCommand(this, this.addNewFolder, this.enableButtons);
	this.setSystemFoldersCommand = Utils.createCommand(this, this.setSystemFolders, this.enableButtons);
	
	this.showMovedWithMouseItem = ko.computed(function () {
		return !App.isMobile();
	}, this);
	this.allowImportExport = ko.observable(ModulesManager.isModuleEnabled('ImportExportMailPlugin'));
	App.subscribeEvent('%ModuleName%::AttemptDeleteNonemptyFolder', _.bind(function () {
		this.highlighted(true);
	}, this));
	
	App.broadcastEvent('%ModuleName%::ConstructView::after', {'Name': 'CAccountFoldersPaneView', 'View': this});
	
	this.afterMove = _.debounce(_.bind(this.folderListOrderUpdate, this), 3000);
}
CMailCache.prototype.showNotificationsForNewMessages = function (oResponse)
{
	var
		sCurrentFolderName = this.folderList().currentFolderFullName(),
		iNewLength = 0,
		sUid = '',
		oParameters = {},
		sFrom = '',
		aBody = []
	;
	
	if (oResponse.Result.New && oResponse.Result.New.length > 0)
	{
		iNewLength = oResponse.Result.New.length;
		sUid = oResponse.Result.New[0].Uid;
		oParameters = {
			action:'show',
			icon: 'static/styles/images/logo_140x140.png',
			title: TextUtils.i18n('%MODULENAME%/INFO_NEW_MESSAGES_PLURAL', {
				'COUNT': iNewLength
			}, null, iNewLength),
			timeout: 5000,
			callback: function () {
				window.focus();
				Routing.setHash(LinksUtils.getMailbox(sCurrentFolderName, 1, sUid, '', ''));
			}
		};

		if (iNewLength === 1)
		{
			if (Types.isNonEmptyString(oResponse.Result.New[0].Subject))
			{
				aBody.push(TextUtils.i18n('%MODULENAME%/LABEL_SUBJECT') + ': ' + oResponse.Result.New[0].Subject);
			}
			
			sFrom = (_.map(oResponse.Result.New[0].From, function(oFrom) {
				return oFrom.DisplayName !== '' ? oFrom.DisplayName : oFrom.Email;
			})).join(', ');
			if (Types.isNonEmptyString(sFrom))
			{
				aBody.push(TextUtils.i18n('%MODULENAME%/LABEL_FROM') + ': ' + sFrom);
			}
			
			oParameters.body = aBody.join('\r\n');
		}

		Utils.desktopNotify(oParameters);
	}
};
CDateModel.prototype.getShortDate = function (bTime)
{
	var
		sResult = '',
		oMomentNow = null
	;

	if (this.oMoment)
	{
		oMomentNow = moment();

		if (oMomentNow.format('L') === this.oMoment.format('L'))
		{
			sResult = this.oMoment.format(this.getTimeFormat());
		}
		else
		{
			if (oMomentNow.clone().subtract(1, 'days').format('L') === this.oMoment.format('L'))
			{
				sResult = TextUtils.i18n('%MODULENAME%/LABEL_YESTERDAY');
			}
			else
			{
				if (UserSettings.UserSelectsDateFormat)
				{
					sResult = this.oMoment.format(Utils.getDateFormatForMoment(UserSettings.dateFormat()));
				}
				else
				{
					if (oMomentNow.year() === this.oMoment.year())
					{
						sResult = this.oMoment.format('MMM D');
					}
					else
					{
						sResult = this.oMoment.format('MMM D, YYYY');
					}
				}
			}

			if (!!bTime)
			{
				sResult += ', ' + this.oMoment.format(this.getTimeFormat());
			}
		}
	}

	return sResult;
};
CForgotView.prototype.onAccountChangeForgotPasswordResponse = function (oResponse, oRequest)
{
	this.changingPassword(false);
	
	if (false === oResponse.Result)
	{
		Api.showErrorByCode(oResponse, TextUtils.i18n('%MODULENAME%/ERROR_RESETTING_PASSWORD'));
	}
	else
	{
		this.gotoForgot(false);
		Utils.log('CForgotView', TextUtils.i18n('%MODULENAME%/REPORT_PASSWORD_CHANGED'));
		Screens.showReport(TextUtils.i18n('%MODULENAME%/REPORT_PASSWORD_CHANGED'));
	}
};
CIdentitySettingsFormView.prototype.save = function ()
{
	if ($.trim(this.email()) === '')
	{
		Screens.showError(Utils.i18n('%MODULENAME%/ERROR_IDENTITY_FIELDS_BLANK'));
	}
	else
	{
		this.isSaving(true);

		this.updateSavedState();

		Ajax.send(this.bCreate ? 'CreateIdentity' : 'UpdateIdentity', this.getParametersForSave(), this.onResponse, this);
	}
};
CFilesView.prototype.filesDrop = function (oFolder, oEvent, oUi)
{
	if (oEvent)
	{
		var
			aChecked = this.selector.listCheckedAndSelected(),
			sMethod = oEvent.ctrlKey ? 'Copy' : 'Move'
		;
		
		if (this.moveItems(sMethod, oFolder, aChecked))
		{
			Utils.uiDropHelperAnim(oEvent, oUi);
		}
	}
};
/**
 * @constructor
 */
function CLoginView()
{
	CAbstractScreenView.call(this, '%ModuleName%');
	
	this.sCustomLogoUrl = Settings.CustomLogoUrl;
	this.sInfoText = Settings.InfoText;
	this.sBottomInfoHtmlText = Settings.BottomInfoHtmlText;
	
	this.login = ko.observable('');
	this.password = ko.observable('');
	
	this.loginFocus = ko.observable(false);
	this.passwordFocus = ko.observable(false);

	this.loading = ko.observable(false);

	this.bUseSignMe = (Settings.LoginSignMeType === Enums.LoginSignMeType.Unuse);
	this.signMe = ko.observable(Enums.LoginSignMeType.DefaultOn === Settings.LoginSignMeType);
	this.signMeFocused = ko.observable(false);

	this.canBeLogin = ko.computed(function () {
		return !this.loading();
	}, this);

	this.signInButtonText = ko.computed(function () {
		return this.loading() ? TextUtils.i18n('COREWEBCLIENT/ACTION_SIGN_IN_IN_PROGRESS') : TextUtils.i18n('COREWEBCLIENT/ACTION_SIGN_IN');
	}, this);

	this.loginCommand = Utils.createCommand(this, this.signIn, this.canBeLogin);

	this.login(Settings.DemoLogin || '');
	this.password(Settings.DemoPassword || '');
	
	this.shake = ko.observable(false).extend({'autoResetToFalse': 800});
	
	this.bRtl = UserSettings.IsRTL;
	this.aLanguages = UserSettings.LanguageList;
	this.currentLanguage = ko.observable(UserSettings.Language);
	this.bAllowChangeLanguage = Settings.AllowChangeLanguage && !App.isMobile();
	this.bUseDropdownLanguagesView = Settings.UseDropdownLanguagesView;

	this.beforeButtonsControllers = ko.observableArray([]);
	App.broadcastEvent('AnonymousUserForm::PopulateBeforeButtonsControllers', { ModuleName: '%ModuleName%', RegisterBeforeButtonsController: this.registerBeforeButtonsController.bind(this) });

	App.broadcastEvent('%ModuleName%::ConstructView::after', {'Name': this.ViewConstructorName, 'View': this});
}
CFilesView.prototype.dragAndDropHelper = function (oFile)
{
	if (oFile)
	{
		oFile.checked(true);
	}

	var
		oHelper = Utils.draggableItems(),
		aItems = this.selector.listCheckedAndSelected(),
		nCount = aItems.length,
		nFilesCount = 0,
		nFoldersCount = 0,
		sText = '';
	
	_.each(aItems, function (oItem) {
		if (oItem instanceof CFolderModel)
		{
			nFoldersCount++;
		}
		else
		{
			nFilesCount++;
		}

	}, this);
	
	if (nFilesCount !== 0 && nFoldersCount !== 0)
	{
		sText = TextUtils.i18n('%MODULENAME%/LABEL_DRAG_ITEMS_PLURAL', {'COUNT': nCount}, null, nCount);
	}
	else if (nFilesCount === 0)
	{
		sText = TextUtils.i18n('%MODULENAME%/LABEL_DRAG_FOLDERS_PLURAL', {'COUNT': nFoldersCount}, null, nFoldersCount);
	}
	else if (nFoldersCount === 0)
	{
		sText = TextUtils.i18n('%MODULENAME%/LABEL_DRAG_FILES_PLURAL', {'COUNT': nFilesCount}, null, nFilesCount);
	}
	
	$('.count-text', oHelper).text(sText);

	return oHelper;
};
CFilesView.prototype.createFolder = function (sFolderName)
{
	sFolderName = $.trim(sFolderName);
	if (!Utils.validateFileOrFolderName(sFolderName))
	{
		return TextUtils.i18n('%MODULENAME%/ERROR_INVALID_FOLDER_NAME');
	}
	else
	{
		Ajax.send('CreateFolder', {
				'Type': this.storageType(),
				'Path': this.currentPath(),
				'FolderName': sFolderName
			}, this.onCreateFolderResponse, this
		);
	}

	return '';
};
CMailView.prototype.resizeDblClick = function (oData, oEvent)
{
	oEvent.preventDefault();
	if (oEvent.stopPropagation)
	{
		oEvent.stopPropagation();
	}
	else
	{
		oEvent.cancelBubble = true;
	}

	Utils.removeSelection();
	if (!this.jqPanelHelper)
	{
		this.jqPanelHelper = $('.MailLayout .panel_helper');
	}
	this.jqPanelHelper.trigger('resize', [600, 'max']);
};
CMailView.prototype.dragAndDropHelper = function (oMessage, bCtrl)
{
	if (oMessage)
	{
		oMessage.checked(true);
	}

	var
		oHelper = Utils.draggableItems(),
		aUids = this.oMessageList.checkedOrSelectedUids(),
		iCount = aUids.length
	;
		
	oHelper.data('p7-message-list-folder', this.folderList().currentFolderFullName());
	oHelper.data('p7-message-list-uids', aUids);

	$('.count-text', oHelper).text(TextUtils.i18n('%MODULENAME%/LABEL_DRAG_MESSAGES_PLURAL', {
		'COUNT': bCtrl ? '+ ' + iCount : iCount
	}, null, iCount));

	return oHelper;
};
CEditEventPopup.prototype.onOpen = function (oParameters)
{
	var
		owner = App.getUserPublicId(),
		oEndMomentDate = null,
		oStartMomentDate = null,
		sAttendee = '',
		oCalendar = null,
		sCalendarOwner = '',
		oToday = moment()
	;

	this.withDate(!!oParameters.Start && !!oParameters.End);

	if (!oParameters.Start && !oParameters.End)
	{
		if (oToday.minutes() > 30)
		{
			oToday.add(60 - oToday.minutes(), 'minutes');
		}
		else
		{
			oToday.minutes(30);
		}
		oToday
			.seconds(0)
			.milliseconds(0);	
		oParameters.Start = oToday;
		oParameters.End = oToday.clone().add(30, 'minutes');
	}
	oEndMomentDate = oParameters.End ? oParameters.End.clone() : null;
	oStartMomentDate = oParameters.Start ? oParameters.Start.clone() : null;
	
	this.iDiffInMinutes = null;

	this.eventType(oParameters.Type || 'VEVENT');
	this.isTask(this.eventType() === 'VTODO');

	this.calendarId(oParameters.SelectedCalendar);
	this.calendars = oParameters.Calendars;

	oCalendar = this.calendars.getCalendarById(this.calendarId());
	if (oCalendar)
	{
		sCalendarOwner = oCalendar.owner();
	}

	this.callbackSave = oParameters.CallbackSave;
	this.callbackDelete = oParameters.CallbackDelete;
	this.callbackAttendeeActionDecline = oParameters.CallbackAttendeeActionDecline;

	this.timeFormatMoment = oParameters.TimeFormat;
	this.dateFormatMoment = Utils.getDateFormatForMoment(oParameters.DateFormat);
	this.dateFormatDatePicker = CalendarUtils.getDateFormatForDatePicker(oParameters.DateFormat);
	
	this.ampmTimeFormat(UserSettings.timeFormat() !== Enums.TimeFormat.F24);
	
	this.initializeDatePickers();
	
	this.allDay(oParameters.AllDay);
	
	if (oStartMomentDate)
	{
		this.setStartDate(oStartMomentDate, true);
		this.startTime(oStartMomentDate.format(this.timeFormatMoment));
	}
	if (oEndMomentDate && this.allDay())
	{
		oEndMomentDate.subtract(1, 'days');
	}
	if (!oEndMomentDate && oStartMomentDate)
	{
		oEndMomentDate = oStartMomentDate;
	}
	if (oEndMomentDate)
	{
		this.setEndDate(oEndMomentDate, true);
		this.endTime(oEndMomentDate.format(this.timeFormatMoment));
	}

	if (this.calendars)
	{
		this.calendarsList(
			_.filter(
				this.calendars.collection(),
				function(oItem){ 
					return oItem.isEditable(); 
				}
			)
		);
	}
	this.selectedCalendarId(oParameters.SelectedCalendar);
	this.selectedCalendarId.valueHasMutated();

	this.changeCalendarColor(this.selectedCalendarId());
	
	// parameters for event editing only (not for creating)
	this.id(oParameters.ID || null);
	this.uid(oParameters.Uid || null);
	this.recurrenceId(oParameters.RecurrenceId || null);
	
	this.subject(oParameters.Subject || '');
	
	this.status(oParameters.Status || false);
	this.location(oParameters.Location || '');
	this.description(oParameters.Description || '');
	this.allEvents(oParameters.AllEvents || Enums.CalendarEditRecurrenceEvent.AllEvents);
	
	this.isTaskApp(oParameters.IsTaskApp || false);

	this.populateAlarms(oParameters.Alarms);

	this.appointment(oParameters.Appointment);

	this.attendees(oParameters.Attendees || []);

	if ($.isFunction(App.getAttendee))
	{
		sAttendee = App.getAttendee(this.attendees());
	}

	this.isMyEvent(sAttendee !== owner && (owner === oParameters.Owner || owner === sCalendarOwner));
	this.editableSwitch(this.selectedCalendarIsShared(), this.selectedCalendarIsEditable(), this.isMyEvent());

	this.setCurrentAttenderStatus(sAttendee, oParameters.Attendees || []);

	this.owner(oParameters.Owner || owner);
	
	this.ownerName(oParameters.OwnerName || (this.isMyEvent() && this.owner() === owner ? owner : ''));
	this.guestAutocomplete('');

	this.excluded(oParameters.Excluded || false);
	this.repeatRuleParse(oParameters.RRule || null);

	if (this.id() === null)
	{
		this.subjectFocus(true);
	}

	this.autosizeTrigger.notifySubscribers(true);
	
	this.modified = false;

	this.isAppointmentButtonsVisible(this.appointment() && this.selectedCalendarIsEditable() && _.find(this.attendees(), function(oAttendee){ return oAttendee.email === owner; }));
};
/**
* @constructor
* @param {boolean=} bPopup = false
*/
function CFilesView(bPopup)
{
	CAbstractScreenView.call(this, '%ModuleName%');
	
	this.browserTitle = ko.observable(TextUtils.i18n('%MODULENAME%/HEADING_BROWSER_TAB'));
	
	this.bAllowSendEmails = _.isFunction(ComposeMessageWithAttachments);
	
	this.error = ko.observable(false);
	this.loaded = ko.observable(false);
	this.bPublic = App.isPublic();
	
	this.storages = ko.observableArray([]);
	this.folders = ko.observableArray();
	this.files = ko.observableArray();
	this.uploadingFiles = ko.observableArray();

	this.rootPath = ko.observable(this.bPublic ? Settings.PublicFolderName : TextUtils.i18n('%MODULENAME%/LABEL_PERSONAL_STORAGE'));
	this.storageType = ko.observable(Enums.FileStorageType.Personal);
	this.storageDisplayName = ko.computed(function () {
		var oStorage = this.getStorageByType(this.storageType());
		return oStorage ? oStorage.displayName : '';
	}, this);
	this.storageType.subscribe(function () {
		if (this.bPublic)
		{
			this.rootPath(Settings.PublicFolderName);
		}
		else
		{
			var oStorage = this.getStorageByType(this.storageType());
			if (oStorage)
			{
				this.rootPath(oStorage.displayName);
			}
			else if (this.storageType() === 'corporate')
			{
				this.rootPath(TextUtils.i18n('%MODULENAME%/LABEL_CORPORATE_STORAGE'));
			}
			this.selector.listCheckedAndSelected(false);
		}
	}, this);
	
	this.pathItems = ko.observableArray();
	this.currentPath = ko.observable('');
	this.dropPath = ko.observable('');
	ko.computed(function () {
		this.dropPath(this.currentPath());
	}, this);
	
	this.filesCollection = ko.computed(function () {
		var aFiles = _.union(this.files(), this.getUploadingFiles());
		
		aFiles.sort(function(left, right) {
			return left.fileName() === right.fileName() ? 0 : (left.fileName() < right.fileName() ? -1 : 1);
		});
		
		return aFiles;
	}, this);
	
	this.collection = ko.computed(function () {
		return _.union(this.folders(), this.filesCollection());
	}, this);
	
	this.columnCount = ko.observable(1);
	
	this.selector = new CSelector(this.collection, _.bind(this.onItemSelect, this),
		_.bind(this.onItemDelete, this), _.bind(this.onItemDblClick, this), _.bind(this.onEnter, this), this.columnCount, true, true, true);
		
	this.firstSelectedFile = ko.computed(function () {
		return _.find(this.selector.listCheckedAndSelected(), function (oItem) {
			return oItem instanceof CFileModel;
		});
	}, this);
	this.selectedCount = ko.computed(function () {
		return this.selector.listCheckedAndSelected().length;
	}, this);
	
	this.searchPattern = ko.observable('');
	this.newSearchPattern = ko.observable('');
	this.isSearchFocused = ko.observable(false);

	this.checkedReadyForOperations = ko.computed(function () {
		var  aItems = this.selector.listCheckedAndSelected() || [];
		return aItems.every(function (oItem)  {
			return !(oItem.uploaded !== undefined && oItem.uploaded() === false || oItem.downloading !== undefined && oItem.downloading() === true);
		});
	}, this);
	this.renameCommand = Utils.createCommand(this, this.executeRename, function () {
		return this.checkedReadyForOperations() && this.selector.listCheckedAndSelected().length === 1 && !this.isDisabledRenameButton();
	});
	this.deleteCommand = Utils.createCommand(this, this.executeDelete, function () {
		return this.checkedReadyForOperations() && this.selector.listCheckedAndSelected().length > 0 && !this.isDisabledDeleteButton();
	});
	this.downloadCommand = Utils.createCommand(this, this.executeDownload, function () {
		if (this.checkedReadyForOperations())
		{
			var oFile = this.getFileIfOnlyOneSelected();
			return !!oFile && oFile.hasAction('download');
		}
		return false;
	});
	this.shareCommand = Utils.createCommand(this, this.executeShare, function () {
		var aItems = this.selector.listCheckedAndSelected();
		return this.checkedReadyForOperations() && 1 === aItems.length && (!aItems[0].bIsLink);
	});
	this.sendCommand = Utils.createCommand(this, this.executeSend, function () {
		if (this.checkedReadyForOperations())
		{
			var
				aItems = this.selector.listCheckedAndSelected(),
				aFileItems = _.filter(aItems, function (oItem) {
					return oItem instanceof CFileModel;
				}, this)
			;
			return (aFileItems.length > 0);
		}
		return false;
	});

	this.uploaderButton = ko.observable(null);
	this.uploaderArea = ko.observable(null);
	this.bDragActive = ko.observable(false);

	this.bDragActiveComp = ko.computed(function () {
		var bDrag = this.bDragActive();
		return bDrag && this.searchPattern() === '';
	}, this);
	
	this.bAllowDragNDrop = false;
	
	this.uploadError = ko.observable(false);
	
	this.quota = ko.observable(0);
	this.used = ko.observable(0);
	this.quotaDesc = ko.observable('');
	this.quotaProc = ko.observable(-1);
	
	ko.computed(function () {
		if (!UserSettings.ShowQuotaBar)
		{
			return true;
		}

		var
			iQuota = this.quota(),
			iUsed = this.used(),
			iProc = 0 < iQuota ? Math.ceil((iUsed / iQuota) * 100) : -1
		;

		iProc = 100 < iProc ? 100 : iProc;
		
		this.quotaProc(iProc);
		this.quotaDesc(-1 < iProc ?
			TextUtils.i18n('COREWEBCLIENT/INFO_QUOTA', {
				'PROC': iProc,
				'QUOTA': TextUtils.getFriendlySize(iQuota)
			}) : '')
		;
		
		if (UserSettings.QuotaWarningPerc > 0 && iProc !== -1 && UserSettings.QuotaWarningPerc > (100 - iProc))
		{
			Screens.showError(TextUtils.i18n('COREWEBCLIENT/WARNING_QUOTA_ALMOST_REACHED'), true);
		}
	}, this);
	
	this.dragover = ko.observable(false);
	
	this.loading = ko.observable(false);
	this.loadedFiles = ko.observable(false);

	this.fileListInfoText = ko.computed(function () {
		var sInfoText = '';
		
		if (this.loading())
		{
			sInfoText = TextUtils.i18n('COREWEBCLIENT/INFO_LOADING');
		}
		else if (this.loadedFiles())
		{
			if (this.collection().length === 0)
			{
				if (this.searchPattern() !== '')
				{
					sInfoText = TextUtils.i18n('%MODULENAME%/INFO_NOTHING_FOUND');
				}
				else
				{
					if (this.currentPath() !== '' || this.bInPopup || this.bPublic)
					{
						sInfoText = TextUtils.i18n('%MODULENAME%/INFO_FOLDER_IS_EMPTY');
					}
					else if (this.bAllowDragNDrop)
					{
						sInfoText = TextUtils.i18n('%MODULENAME%/INFO_DRAGNDROP_FILES_OR_CREATE_FOLDER');
					}
				}
			}
		}
		else if (this.error())
		{
			sInfoText = TextUtils.i18n('%MODULENAME%/ERROR_FILES_NOT_RECEIVED');
		}
		
		return sInfoText;
	}, this);
	
	this.dragAndDropHelperBound = _.bind(this.dragAndDropHelper, this);
	this.bInPopup = !!bPopup;
	this.isCurrentStorageExternal = ko.computed(function () {
		var oStorage = this.getStorageByType(this.storageType());
		return (oStorage && oStorage.isExternal);
	}, this);
	this.timerId = null;
	
	var oParams = {
		'View': this,
		'TemplateName': '%ModuleName%_ItemsView'
	};
	this.itemsViewTemplate = ko.observable(oParams.TemplateName);
	App.broadcastEvent('Files::ChangeItemsView', oParams);
	
	this.addToolbarButtons = ko.observableArray([]);
	
	App.subscribeEvent('Files::ShowList', _.bind(function (oParams) {
		if (oParams.Item)
		{
			this.routeFiles(oParams.Item.storageType(), oParams.Item.fullPath());
		}
	}, this));
	App.broadcastEvent('%ModuleName%::ConstructView::after', {'Name': this.ViewConstructorName, 'View': this});
	
	ConfirmPopup.opened.subscribe(_.bind(function() {
		if (this.shown())
		{
			this.selector.useKeyboardKeys(true);
		}
	}, this));
	
	this.createFolderButtonModules = ko.observableArray([]);	//list of modules that disable "create folder" button
	this.renameButtonModules = ko.observableArray([]);	//list of modules that disable "rename" button
	this.deleteButtonModules = ko.observableArray([]);	//list of modules that disable "delete" button
	this.shortcutButtonModules = ko.observableArray([]);	//list of modules that disable "shortcut" button
	this.isDisabledCreateFolderButton = ko.computed(function () {
		return this.createFolderButtonModules().length > 0;
	}, this);
	this.isDisabledRenameButton = ko.computed(function () {
		return this.renameButtonModules().length > 0;
	}, this);
	this.isDisabledDeleteButton = ko.computed(function () {
		return this.deleteButtonModules().length > 0;
	}, this);
	this.isDisabledShortcutButton = ko.computed(function () {
		return this.shortcutButtonModules().length > 0;
	}, this);
	this.createFolderCommand = Utils.createCommand(this, this.executeCreateFolder, function () {
		return !this.isDisabledCreateFolderButton();
	});
	this.createShortcutCommand = Utils.createCommand(this, this.executeCreateShortcut, function () {
		return !this.isDisabledShortcutButton();
	});
}
	'init': function (oElement, fValueAccessor, fAllBindingsAccessor, oViewModel, bindingContext) {

		var
			jqEl = $(oElement),
			oOptions = fValueAccessor(),
			fCallback = oOptions['callback'],
			fDataAccessor = oOptions.dataAccessor ? oOptions.dataAccessor : Utils.emptyFunction(),
			fDelete = function () {
				fDeleteAccessor(oSelectedItem);
				var oAutocomplete = jqEl.data('customAutocomplete') || jqEl.data('uiAutocomplete') || jqEl.data('autocomplete') || jqEl.data('ui-autocomplete');
				$.ui.autocomplete.prototype.__response.call(oAutocomplete, _.filter(aSourceResponseItems, function (oItem) { return oItem.value !== oSelectedItem.value; }));
			},
			aSourceResponseItems = null,
			oSelectedItem = null
		;

		if (fCallback && jqEl && jqEl[0])
		{
			jqEl.autocomplete({
				'minLength': 1,
				'autoFocus': true,
				'position': {
					collision: "flip" //prevents the escape off the screen
				},
				'source': function (oRequest, fSourceResponse) {
					fCallback(oRequest, function (oItems) { //additional layer for story oItems
						aSourceResponseItems = oItems;
						fSourceResponse(oItems);
					});
				},
				'focus': function (oEvent, oItem) {
					oSelectedItem = oItem.item;
				},
				'open': function (oEvent, oItem) {
					$(jqEl.autocomplete('widget')).find('span.del').on('click', function(oEvent, oItem) {
						Utils.calmEvent(oEvent);
						fDelete();
					});
				},
				'select': function (oEvent, oItem) {
					_.delay(function () {
						jqEl.trigger('change');
					}, 5);
					fDataAccessor(oItem.item);

					return true;
				}
			}).on('click', function(oEvent, oItem) {
				if (jqEl.val() === '')
				{
					if (!$(jqEl.autocomplete('widget')).is(':visible'))
					{
						jqEl.autocomplete("option", "minLength", 0); //for triggering search on empty field
						jqEl.autocomplete("search");
						jqEl.autocomplete("option", "minLength", 1);
					}
					else
					{
						jqEl.autocomplete("close");
					}
				}
			}).on('keydown', function(oEvent, oItem) {
				if (aSourceResponseItems && oSelectedItem && !oSelectedItem.global && oEvent.keyCode === Enums.Key.Del && oEvent.shiftKey) //shift+del on suggestions list
				{
					Utils.calmEvent(oEvent);
					fDelete();
				}
			});
		}
	}
					$(jqEl.autocomplete('widget')).find('span.del').on('click', function(oEvent, oItem) {
						Utils.calmEvent(oEvent);
						fDelete();
					});
/**
 * @constructor
 */
function CMailView()
{
	CAbstractScreenView.call(this, '%ModuleName%');
	
	App.broadcastEvent('%ModuleName%::ConstructView::before', {'Name': this.ViewConstructorName, 'View': this, 'MailCache': MailCache});
	
	this.browserTitle = ko.computed(function () {
		return AccountList.getEmail() + ' - ' + TextUtils.i18n('%MODULENAME%/HEADING_BROWSER_TAB');
	});
	
	this.folderList = MailCache.folderList;
	this.domFoldersMoveTo = ko.observable(null);
	
	this.openMessageInNewWindowBound = _.bind(this.openMessageInNewWindow, this);
	
	this.oFolderList = new CFolderListView();
	this.oMessageList = new CMessageListView(this.openMessageInNewWindowBound);
	
	this.oBaseMessagePaneView = MessagePaneView;
	this.messagePane = ko.observable(this.oBaseMessagePaneView);
	this.messagePane().openMessageInNewWindowBound = this.openMessageInNewWindowBound;
	this.messagePane.subscribe(function () {
		this.bindMessagePane();
	}, this);

	this.isEnableGroupOperations = this.oMessageList.isEnableGroupOperations;

	this.composeLink = ko.observable(Routing.buildHashFromArray(LinksUtils.getCompose()));
	this.sCustomBigButtonModule = '';
	this.fCustomBigButtonHandler = null;
	this.customBigButtonText = ko.observable('');
	this.bigButtonCommand = Utils.createCommand(this, function () {
		if (_.isFunction(this.fCustomBigButtonHandler))
		{
			this.fCustomBigButtonHandler();
		}
		else
		{
			this.executeCompose();
		}
	});
	this.bigButtonText = ko.computed(function () {
		if (this.customBigButtonText() !== '')
		{
			return this.customBigButtonText();
		}
		return TextUtils.i18n('%MODULENAME%/ACTION_NEW_MESSAGE');
	}, this);

	this.checkMailCommand = Utils.createCommand(this, this.executeCheckMail);
	this.checkMailIndicator = ko.observable(true).extend({ throttle: 50 });
	ko.computed(function () {
		this.checkMailIndicator(MailCache.checkMailStarted() || MailCache.messagesLoading());
	}, this);
	this.customModulesDisabledMark = ko.observableArray([]);
	this.visibleMarkTool = ko.computed(function () {
		return !Types.isNonEmptyArray(this.customModulesDisabledMark());
	}, this);
	this.markAsReadCommand = Utils.createCommand(this.oMessageList, this.oMessageList.executeMarkAsRead, this.isEnableGroupOperations);
	this.markAsUnreadCommand = Utils.createCommand(this.oMessageList, this.oMessageList.executeMarkAsUnread, this.isEnableGroupOperations);
	this.markAllReadCommand = Utils.createCommand(this.oMessageList, this.oMessageList.executeMarkAllRead);
	this.customModulesDisabledMove = ko.observableArray([]);
	this.visibleMoveTool = ko.computed(function () {
		return !Types.isNonEmptyArray(this.customModulesDisabledMove());
	}, this);
	this.moveToFolderCommand = Utils.createCommand(this, function () {}, this.isEnableGroupOperations);
//	this.copyToFolderCommand = Utils.createCommand(this, function () {}, this.isEnableGroupOperations);
	this.deleteCommand = Utils.createCommand(this.oMessageList, this.oMessageList.executeDelete, this.isEnableGroupOperations);
	this.selectedCount = ko.computed(function () {
		return this.oMessageList.checkedUids().length;
	}, this);
	this.emptyTrashCommand = Utils.createCommand(MailCache, MailCache.executeEmptyTrash, this.oMessageList.isNotEmptyList);
	this.emptySpamCommand = Utils.createCommand(MailCache, MailCache.executeEmptySpam, this.oMessageList.isNotEmptyList);
	this.spamCommand = Utils.createCommand(this.oMessageList, this.oMessageList.executeSpam, this.isEnableGroupOperations);
	this.notSpamCommand = Utils.createCommand(this.oMessageList, this.oMessageList.executeNotSpam, this.isEnableGroupOperations);

	this.isVisibleReplyTool = ko.computed(function () {
		return (this.folderList().currentFolder() &&
			this.folderList().currentFolderFullName().length > 0 &&
			this.folderList().currentFolderType() !== Enums.FolderTypes.Drafts &&
			this.folderList().currentFolderType() !== Enums.FolderTypes.Sent);
	}, this);

	this.isVisibleForwardTool = ko.computed(function () {
		return (this.folderList().currentFolder() &&
			this.folderList().currentFolderFullName().length > 0 &&
			this.folderList().currentFolderType() !== Enums.FolderTypes.Drafts);
	}, this);

	this.isSpamFolder = ko.computed(function () {
		return this.folderList().currentFolderType() === Enums.FolderTypes.Spam;
	}, this);
	
	this.customModulesDisabledSpam = ko.observableArray([]);
	this.allowedSpamAction = ko.computed(function () {
		return Settings.AllowSpamFolder && this.folderList().spamFolder() && !this.isSpamFolder() && !Types.isNonEmptyArray(this.customModulesDisabledSpam());
	}, this);
	
	this.allowedNotSpamAction = ko.computed(function () {
		return Settings.AllowSpamFolder && this.isSpamFolder();
	}, this);
	
	this.isTrashFolder = ko.computed(function () {
		return this.folderList().currentFolderType() === Enums.FolderTypes.Trash;
	}, this);

	this.jqPanelHelper = null;
	
	if (Settings.HorizontalLayout)
	{
		$('html').addClass('layout-horiz-split');
	}
	
	App.broadcastEvent('%ModuleName%::ConstructView::after', {'Name': this.ViewConstructorName, 'View': this});
}