/* globals fileUpload KonchatNotification chatMessages popover AudioRecorder chatMessages fileUploadHandler*/
import toastr from 'toastr';
import moment from 'moment';
import _ from 'underscore';

let audioMessageIntervalId;

function katexSyntax() {
	if (RocketChat.katex.katex_enabled()) {
		if (RocketChat.katex.dollar_syntax_enabled()) {
			return '$$KaTeX$$';
		}
		if (RocketChat.katex.parenthesis_syntax_enabled()) {
			return '\\[KaTeX\\]';
		}
	}
	return false;
}

function applyMd(e, t) {
	if (e.currentTarget.dataset.link) {
		return false;
	}

	e.preventDefault();
	const box = t.find('.js-input-message');
	const { selectionEnd = box.value.length, selectionStart = 0 } = box;
	const initText = box.value.slice(0, selectionStart);
	const selectedText = box.value.slice(selectionStart, selectionEnd);
	const finalText = box.value.slice(selectionEnd, box.value.length);

	const [btn] = t.findAll(`.js-md[aria-label=${ this.label }]`);
	if (btn) {
		btn.classList.add('active');
		setTimeout(function() {
			btn.classList.remove('active');
		}, 100);
	}
	box.focus();

	// removes markdown if selected text in inside the same clicked markdown
	const startPattern = this.pattern.substr(0, this.pattern.indexOf('{{text}}'));
	const startPatternFound = [...startPattern].reverse().every((char, index) => box.value.substr(selectionStart - index - 1, 1) === char);

	if (startPatternFound) {
		const endPattern = this.pattern.substr(this.pattern.indexOf('{{text}}') + '{{text}}'.length);
		const endPatternFound = [...endPattern].every((char, index) => box.value.substr(selectionEnd + index, 1) === char);

		if (endPatternFound) {
			box.selectionStart = selectionStart - startPattern.length;
			box.selectionEnd = selectionEnd + endPattern.length;

			if (!document.execCommand || !document.execCommand('insertText', false, selectedText)) {
				box.value = initText.substr(0, initText.length - startPattern.length) + selectedText + finalText.substr(endPattern.length);
			}

			box.selectionStart = selectionStart - startPattern.length;
			box.selectionEnd = box.selectionStart + selectedText.length;
			$(box).change();
			return;
		}
	}

	/*
		get text
		apply pattern
		restore selection
	*/
	if (!document.execCommand || !document.execCommand('insertText', false, this.pattern.replace('{{text}}', selectedText))) {
		box.value = initText + this.pattern.replace('{{text}}', selectedText) + finalText;
	}

	box.selectionStart = selectionStart + this.pattern.indexOf('{{text}}');
	box.selectionEnd = box.selectionStart + selectedText.length;
	$(box).change();
}


const markdownButtons = [
	{
		label: 'bold',
		icon: 'bold',
		pattern: '*{{text}}*',
		command: 'b',
		condition: () => RocketChat.Markdown && RocketChat.settings.get('Markdown_Parser') === 'original',
	},
	{
		label: 'bold',
		icon: 'bold',
		pattern: '**{{text}}**',
		command: 'b',
		condition: () => RocketChat.Markdown && RocketChat.settings.get('Markdown_Parser') === 'marked',
	},
	{
		label: 'italic',
		icon: 'italic',
		pattern: '_{{text}}_',
		command: 'i',
		condition: () => RocketChat.Markdown && RocketChat.settings.get('Markdown_Parser') !== 'disabled',
	},
	{
		label: 'strike',
		icon: 'strike',
		pattern: '~{{text}}~',
		condition: () => RocketChat.Markdown && RocketChat.settings.get('Markdown_Parser') === 'original',
	},
	{
		label: 'strike',
		icon: 'strike',
		pattern: '~~{{text}}~~',
		condition: () => RocketChat.Markdown && RocketChat.settings.get('Markdown_Parser') === 'marked',
	},
	{
		label: 'inline_code',
		icon: 'code',
		pattern: '`{{text}}`',
		condition: () => RocketChat.Markdown && RocketChat.settings.get('Markdown_Parser') !== 'disabled',
	},
	{
		label: 'multi_line',
		icon: 'multi-line',
		pattern: '```\n{{text}}\n``` ',
		condition: () => RocketChat.Markdown && RocketChat.settings.get('Markdown_Parser') !== 'disabled',
	},
	{
		label: katexSyntax,
		link: 'https://khan.github.io/KaTeX/function-support.html',
		condition: () => RocketChat.katex.katex_enabled(),
	},
];

const methods = {
	actions() {
		const groups = RocketChat.messageBox.actions.get();
		return Object.keys(groups).reduce((ret, el) => ret.concat(groups[el]), []);
	},
};

Template.messageBox__actions.helpers(methods);
Template.messageBox__actionsSmall.helpers(methods);
Template.messageBox.helpers({
	mdButtons() {
		return markdownButtons.filter((button) => !button.condition || button.condition());
	},
	roomName() {
		const roomData = Session.get(`roomData${ this._id }`);
		if (!roomData) {
			return '';
		}
		if (roomData.t === 'd') {
			const chat = ChatSubscription.findOne({
				rid: this._id,
			}, {
				fields: {
					name: 1,
				},
			});
			return chat && chat.name;
		} else {
			return roomData.name;
		}
	},
	showFormattingTips() {
		return RocketChat.settings.get('Message_ShowFormattingTips');
	},
	canJoin() {
		return Meteor.userId() && RocketChat.roomTypes.verifyShowJoinLink(this._id);
	},
	joinCodeRequired() {
		const code = Session.get(`roomData${ this._id }`);
		return code && code.joinCodeRequired;
	},
	subscribed() {
		return RocketChat.roomTypes.verifyCanSendMessage(this._id);
	},
	allowedToSend() {
		if (RocketChat.roomTypes.readOnly(this._id, Meteor.user())) {
			return false;
		}
		if (RocketChat.roomTypes.archived(this._id)) {
			return false;
		}
		const roomData = Session.get(`roomData${ this._id }`);
		if (roomData && roomData.t === 'd') {
			const subscription = ChatSubscription.findOne({
				rid: this._id,
			}, {
				fields: {
					archived: 1,
					blocked: 1,
					blocker: 1,
				},
			});
			if (subscription && (subscription.archived || subscription.blocked || subscription.blocker)) {
				return false;
			}
		}
		return true;
	},
	isBlockedOrBlocker() {
		const roomData = Session.get(`roomData${ this._id }`);
		if (roomData && roomData.t === 'd') {
			const subscription = ChatSubscription.findOne({
				rid: this._id,
			}, {
				fields: {
					blocked: 1,
					blocker: 1,
				},
			});
			if (subscription && (subscription.blocked || subscription.blocker)) {
				return true;
			}
		}
	},
	getPopupConfig() {
		const template = Template.instance();
		return {
			getInput() {
				return template.find('.js-input-message');
			},
		};
	},
	/* globals MsgTyping*/
	usersTyping() {
		const users = MsgTyping.get(this._id);
		if (users.length === 0) {
			return;
		}
		if (users.length === 1) {
			return {
				multi: false,
				selfTyping: MsgTyping.selfTyping.get(),
				users: users[0],
			};
		}
		let last = users.pop();
		if (users.length > 4) {
			last = t('others');
		}
		let usernames = users.join(', ');
		usernames = [usernames, last];
		return {
			multi: true,
			selfTyping: MsgTyping.selfTyping.get(),
			users: usernames.join(` ${ t('and') } `),
		};
	},
	groupAttachHidden() {
		if (RocketChat.settings.get('Message_Attachments_GroupAttach')) {
			return 'hidden';
		}
	},
	notSubscribedTpl() {
		return RocketChat.roomTypes.getNotSubscribedTpl(this._id);
	},
	anonymousRead() {
		return (Meteor.userId() == null) && RocketChat.settings.get('Accounts_AllowAnonymousRead') === true;
	},
	anonymousWrite() {
		return (Meteor.userId() == null) && RocketChat.settings.get('Accounts_AllowAnonymousRead') === true && RocketChat.settings.get('Accounts_AllowAnonymousWrite') === true;
	},
	disableSendIcon() {
		return !Template.instance().sendIcon.get() ? 'disabled' : '';
	},
	embeddedVersion() {
		return RocketChat.Layout.isEmbedded();
	},
	isEmojiEnable() {
		return RocketChat.getUserPreference(Meteor.user(), 'useEmojis');
	},
	dataReply() {
		return Template.instance().dataReply.get();
	},
	isAudioMessageAllowed() {
		return (navigator.getUserMedia || navigator.webkitGetUserMedia ||
			navigator.mozGetUserMedia || navigator.msGetUserMedia) &&
			RocketChat.settings.get('FileUpload_Enabled') &&
			RocketChat.settings.get('Message_AudioRecorderEnabled') &&
			(!RocketChat.settings.get('FileUpload_MediaTypeWhiteList') ||
			RocketChat.settings.get('FileUpload_MediaTypeWhiteList').match(/audio\/mp3|audio\/\*/i));
	},
});

function firefoxPasteUpload(fn) {
	const user = navigator.userAgent.match(/Firefox\/(\d+)\.\d/);
	if (!user || user[1] > 49) {
		return fn;
	}
	return function(event, instance, ...args) {
		if ((event.originalEvent.ctrlKey || event.originalEvent.metaKey) && (event.keyCode === 86)) {
			const textarea = instance.find('textarea');
			const { selectionStart, selectionEnd } = textarea;
			const contentEditableDiv = instance.find('#msg_contenteditable');
			contentEditableDiv.focus();
			Meteor.setTimeout(function() {
				const pastedImg = contentEditableDiv.querySelector('img');
				const textareaContent = textarea.value;
				const startContent = textareaContent.substring(0, selectionStart);
				const endContent = textareaContent.substring(selectionEnd);
				const restoreSelection = function(pastedText) {
					textarea.value = startContent + pastedText + endContent;
					textarea.selectionStart = selectionStart + pastedText.length;
					return textarea.selectionEnd = textarea.selectionStart;
				};
				if (pastedImg) {
					contentEditableDiv.innerHTML = '';
				}
				textarea.focus;
				if (!pastedImg || contentEditableDiv.innerHTML.length > 0) {
					return [].slice.call(contentEditableDiv.querySelectorAll('br')).forEach(function(el) {
						contentEditableDiv.replaceChild(new Text('\n'), el);
						return restoreSelection(contentEditableDiv.innerText);
					});
				}
				const imageSrc = pastedImg.getAttribute('src');
				if (imageSrc.match(/^data:image/)) {
					return fetch(imageSrc).then(function(img) {
						return img.blob();
					}).then(function(blob) {
						return fileUpload([
							{
								file: blob,
								name: 'Clipboard',
							},
						]);
					});
				}
			}, 150);
		}
		return fn && fn.apply(this, [event, instance, ...args]);
	};
}

Template.messageBox.events({
	'click .js-message-actions .rc-popover__item, click .js-message-actions .js-message-action'(event, instance) {
		const action = this.action || Template.parentData().action;
		action.apply(this, [{ rid: Template.parentData()._id, messageBox: instance.find('.rc-message-box'), element: event.currentTarget, event }]);
	},
	'click .join'(event) {
		event.stopPropagation();
		event.preventDefault();
		Meteor.call('joinRoom', this._id, Template.instance().$('[name=joinCode]').val(), (err) => {
			if (err != null) {
				toastr.error(t(err.reason));
			}
			if (RocketChat.authz.hasAllPermission('preview-c-room') === false && RoomHistoryManager.getRoom(this._id).loaded === 0) {
				RoomManager.getOpenedRoomByRid(this._id).streamActive = false;
				RoomManager.getOpenedRoomByRid(this._id).ready = false;
				RoomHistoryManager.getRoom(this._id).loaded = null;
				RoomManager.computation.invalidate();
			}
		});
	},

	'click .register'(event) {
		event.stopPropagation();
		event.preventDefault();
		return Session.set('forceLogin', true);
	},
	'click .register-anonymous'(event) {
		event.stopPropagation();
		event.preventDefault();
		return Meteor.call('registerUser', {}, function(error, loginData) {
			if (loginData && loginData.token) {
				return Meteor.loginWithToken(loginData.token);
			}
		});
	},
	'focus .js-input-message'(event, instance) {
		KonchatNotification.removeRoomNotification(this._id);
		if (chatMessages[this._id]) {
			chatMessages[this._id].input = instance.find('.js-input-message');
		}
	},
	'click .js-send'(event, instance) {
		const input = instance.find('.js-input-message');
		chatMessages[this._id].send(this._id, input, () => {
			// fixes https://github.com/RocketChat/Rocket.Chat/issues/3037
			// at this point, the input is cleared and ready for autogrow
			input.updateAutogrow();
			instance.isMessageFieldEmpty.set(chatMessages[this._id].isEmpty());
			return input.focus();
		});
	},
	'click .cancel-reply'(event, instance) {
		const input = instance.find('.js-input-message');
		$(input)
			.focus()
			.removeData('reply')
			.trigger('dataChange');
	},
	'keyup .js-input-message'(event, instance) {
		chatMessages[this._id].keyup(this._id, event, instance);
		return instance.isMessageFieldEmpty.set(chatMessages[this._id].isEmpty());
	},
	'paste .js-input-message'(e, instance) {
		Meteor.setTimeout(function() {
			const input = instance.find('.js-input-message');
			return typeof input.updateAutogrow === 'function' && input.updateAutogrow();
		}, 50);
		if (e.originalEvent.clipboardData == null) {
			return;
		}
		const items = [...e.originalEvent.clipboardData.items];
		const files = items
			.filter((item) => (item.kind === 'file' && item.type.indexOf('image/') !== -1))
			.map((item) => {
				e.preventDefault();
				return {
					file: item.getAsFile(),
					name: `Clipboard - ${ moment().format(RocketChat.settings.get('Message_TimeAndDateFormat')) }`,
				};
			});
		if (files.length) {
			return fileUpload(files);
		} else {
			return instance.isMessageFieldEmpty.set(false);
		}
	},
	'keydown .js-input-message': firefoxPasteUpload(function(event, t) {
		if ((navigator.platform.indexOf('Mac') !== -1 && event.metaKey) || (navigator.platform.indexOf('Mac') === -1 && event.ctrlKey)) {
			const action = markdownButtons.find((action) => action.command === event.key.toLowerCase() && (!action.condition || action.condition()));
			if (action) {
				applyMd.apply(action, [event, t]);
			}
		}
		return chatMessages[this._id].keydown(this._id, event, Template.instance());
	}),
	'input .js-input-message'(event, instance) {
		instance.sendIcon.set(event.target.value !== '');
		return chatMessages[this._id].valueChanged(this._id, event, Template.instance());
	},
	'propertychange .js-input-message'(event) {
		if (event.originalEvent.propertyName === 'value') {
			return chatMessages[this._id].valueChanged(this._id, event, Template.instance());
		}
	},
	'click .editing-commands-cancel > button'() {
		return chatMessages[this._id].clearEditing();
	},
	'click .editing-commands-save > button'() {
		return chatMessages[this._id].send(this._id, chatMessages[this._id].input);
	},
	'click .js-md'(e, t) {
		applyMd.apply(this, [e, t]);
	},
	'click .rc-message-box__action-menu'(e) {
		const groups = RocketChat.messageBox.actions.get();
		const config = {
			popoverClass: 'message-box',
			columns: [
				{
					groups: Object.keys(groups).map((group) => {
						const items = [];
						groups[group].forEach((item) => {
							items.push({
								icon: item.icon,
								name: t(item.label),
								type: 'messagebox-action',
								id: item.id,
							});
						});
						return {
							title: t(group),
							items,
						};
					}),
				},
			],
			offsetVertical: 10,
			direction: 'top-inverted',
			currentTarget: e.currentTarget.firstElementChild.firstElementChild,
			data: {
				rid: this._id,
			},
			activeElement: e.currentTarget,
		};

		popover.open(config);
	},
	'click .js-audio-message-record'(event) {
		event.preventDefault();
		const recording_icons = document.querySelectorAll('.rc-message-box__icon.check, .rc-message-box__icon.cross, .rc-message-box__timer-box');
		const timer = document.querySelector('.rc-message-box__timer');
		const mic = document.querySelector('.rc-message-box__icon.mic');

		chatMessages[RocketChat.openedRoom].recording = true;
		AudioRecorder.start(function() {
			const startTime = new Date;
			timer.innerHTML = '00:00';
			audioMessageIntervalId = setInterval(() => {
				const now = new Date;
				const distance = now - startTime;
				let minutes = Math.floor(distance / (1000 * 60));
				let seconds = Math.floor((distance % (1000 * 60)) / 1000);
				if (minutes < 10) { minutes = `0${ minutes }`; }
				if (seconds < 10) { seconds = `0${ seconds }`; }
				timer.innerHTML = `${ minutes }:${ seconds }`;
			}, 1000);

			mic.classList.remove('active');
			recording_icons.forEach((e) => { e.classList.add('active'); });
		});
	},
	'click .js-audio-message-cross'(event) {
		event.preventDefault();
		const timer = document.querySelector('.rc-message-box__timer');
		const mic = document.querySelector('.rc-message-box__icon.mic');
		const recording_icons = document.querySelectorAll('.rc-message-box__icon.check, .rc-message-box__icon.cross, .rc-message-box__timer-box');

		recording_icons.forEach((e) => { e.classList.remove('active'); });
		mic.classList.add('active');
		timer.innerHTML = '00:00';
		if (audioMessageIntervalId) {
			clearInterval(audioMessageIntervalId);
		}

		AudioRecorder.stop();
		chatMessages[RocketChat.openedRoom].recording = false;
	},
	'click .js-audio-message-check'(event) {
		event.preventDefault();
		const timer = document.querySelector('.rc-message-box__timer');
		const mic = document.querySelector('.rc-message-box__icon.mic');
		const loader = document.querySelector('.js-audio-message-loading');
		const recording_icons = document.querySelectorAll('.rc-message-box__icon.check, .rc-message-box__icon.cross, .rc-message-box__timer-box');

		recording_icons.forEach((e) => { e.classList.remove('active'); });
		loader.classList.add('active');
		timer.innerHTML = '00:00';
		if (audioMessageIntervalId) {
			clearInterval(audioMessageIntervalId);
		}

		chatMessages[RocketChat.openedRoom].recording = false;
		AudioRecorder.stop(function(blob) {

			loader.classList.remove('active');
			mic.classList.add('active');
			const roomId = Session.get('openedRoom');
			const record = {
				name: `${ TAPi18n.__('Audio record') }.mp3`,
				size: blob.size,
				type: 'audio/mp3',
				rid: roomId,
				description: '',
			};
			const upload = fileUploadHandler('Uploads', record, blob);
			let uploading = Session.get('uploading') || [];
			uploading.push({
				id: upload.id,
				name: upload.getFileName(),
				percentage: 0,
			});
			Session.set('uploading', uploading);
			upload.onProgress = function(progress) {
				uploading = Session.get('uploading');

				const item = _.findWhere(uploading, { id: upload.id });
				if (item != null) {
					item.percentage = Math.round(progress * 100) || 0;
					return Session.set('uploading', uploading);
				}
			};

			upload.start(function(error, file, storage) {
				if (error) {
					let uploading = Session.get('uploading');
					if (!Array.isArray(uploading)) {
						uploading = [];
					}

					const item = _.findWhere(uploading, { id: upload.id });

					if (_.isObject(item)) {
						item.error = error.message;
						item.percentage = 0;
					} else {
						uploading.push({
							error: error.error,
							percentage: 0,
						});
					}

					Session.set('uploading', uploading);
					return;
				}


				if (file) {
					Meteor.call('sendFileMessage', roomId, storage, file, () => {
						Meteor.setTimeout(() => {
							const uploading = Session.get('uploading');
							if (uploading !== null) {
								const item = _.findWhere(uploading, {
									id: upload.id,
								});
								return Session.set('uploading', _.without(uploading, item));
							}
						}, 2000);
					});
				}
			});

			Tracker.autorun(function(c) {
				const cancel = Session.get(`uploading-cancel-${ upload.id }`);
				if (cancel) {
					let item;
					upload.stop();
					c.stop();

					uploading = Session.get('uploading');
					if (uploading != null) {
						item = _.findWhere(uploading, { id: upload.id });
						if (item != null) {
							item.percentage = 0;
						}
						Session.set('uploading', uploading);
					}

					return Meteor.setTimeout(function() {
						uploading = Session.get('uploading');
						if (uploading != null) {
							item = _.findWhere(uploading, { id: upload.id });
							return Session.set('uploading', _.without(uploading, item));
						}
					}, 1000);
				}
			});
		});
		return false;
	},
});

Template.messageBox.onRendered(function() {
	const input = this.find('.js-input-message'); // mssg box
	const self = this;
	$(input).on('dataChange', () => {
		const reply = $(input).data('reply');
		self.dataReply.set(reply);
	});
	chatMessages[RocketChat.openedRoom] = chatMessages[RocketChat.openedRoom] || new ChatMessages;
	chatMessages[RocketChat.openedRoom].input = this.$('.js-input-message').autogrow({
		animate: true,
		onInitialize: true,
	}).on('autogrow', () => {
		this.data && this.data.onResize && this.data.onResize();
	}).focus()[0];
});

Template.messageBox.onCreated(function() {
	this.dataReply = new ReactiveVar(''); // if user is replying to a mssg, this will contain data of the mssg being replied to
	this.isMessageFieldEmpty = new ReactiveVar(true);
	this.sendIcon = new ReactiveVar(false);
});

Meteor.startup(function() {
	RocketChat.Geolocation = new ReactiveVar(false);
	Tracker.autorun(function() {
		const MapView_GMapsAPIKey = RocketChat.settings.get('MapView_GMapsAPIKey');
		if (RocketChat.settings.get('MapView_Enabled') === true && MapView_GMapsAPIKey && MapView_GMapsAPIKey.length && navigator.geolocation && navigator.geolocation.getCurrentPosition) {
			const success = (position) => RocketChat.Geolocation.set(position);
			const error = (error) => {
				console.log('Error getting your geolocation', error);
				return RocketChat.Geolocation.set(false);
			};
			const options = {
				enableHighAccuracy: true,
				maximumAge: 0,
				timeout: 10000,
			};
			return navigator.geolocation.watchPosition(success, error, options);
		} else {
			return RocketChat.Geolocation.set(false);
		}
	});
	RocketChat.callbacks.add('enter-room', function() {
		setTimeout(() => {
			if (chatMessages[RocketChat.openedRoom].input) {
				chatMessages[RocketChat.openedRoom].input.focus();
				chatMessages[RocketChat.openedRoom].restoreText(RocketChat.openedRoom);
			}
		}, 200);
	});
});
