text: import { Match, check } from 'meteor/check';
  import { Markdown } from '../../../markdown';
  import { Messages } from '../../../models';
  
  const objectMaybeIncluding = (types) => Match.Where((value) => {
  	Object.keys(types).forEach((field) => {
  		if (value[field] != null) {
  			try {
  				check(value[field], types[field]);
  			} catch (error) {
  				error.path = field;
  				throw error;
  			}
  		}
  	});
  
  	return true;
  });
  
  const validateAttachmentsFields = (attachmentField) => {
  	check(attachmentField, objectMaybeIncluding({
  		short: Boolean,
  		title: String,
  		value: Match.OneOf(String, Match.Integer, Boolean),
  	}));
  
  	if (typeof attachmentField.value !== 'undefined') {
  		attachmentField.value = String(attachmentField.value);
  	}
  };
  
  const validateAttachmentsActions = (attachmentActions) => {
  	check(attachmentActions, objectMaybeIncluding({
  		type: String,
  		text: String,
  		url: String,
  		image_url: String,
  		is_webview: Boolean,
  		webview_height_ratio: String,
  		msg: String,
  		msg_in_chat_window: Boolean,
  	}));
  };
  
  const validateAttachment = (attachment) => {
  	check(attachment, objectMaybeIncluding({
  		color: String,
  		text: String,
  		ts: Match.OneOf(String, Match.Integer),
  		thumb_url: String,
  		button_alignment: String,
  		actions: [Match.Any],
  		message_link: String,
  		collapsed: Boolean,
  		author_name: String,
  		author_link: String,
  		author_icon: String,
  		title: String,
  		title_link: String,
  		title_link_download: Boolean,
  		image_url: String,
  		audio_url: String,
  		video_url: String,
  		fields: [Match.Any],
  	}));
  
  	if (attachment.fields && attachment.fields.length) {
  		attachment.fields.map(validateAttachmentsFields);
  	}
  
  	if (attachment.actions && attachment.actions.length) {
  		attachment.actions.map(validateAttachmentsActions);
  	}
  };
  
  const validateBodyAttachments = (attachments) => attachments.map(validateAttachment);
  
  export const insertMessage = function(user, message, room, upsert = false) {
  	if (!user || !message || !room._id) {
  		return false;
  	}
  
  	check(message, objectMaybeIncluding({
  		_id: String,
  		msg: String,
  		text: String,
  		alias: String,
  		emoji: String,
  		avatar: String,
  		attachments: [Match.Any],
  	}));
  
  	if (Array.isArray(message.attachments) && message.attachments.length) {
  		validateBodyAttachments(message.attachments);
  	}
  
  	if (!message.ts) {
  		message.ts = new Date();
  	}
  	const { _id, username } = user;
  	message.u = {
  		_id,
  		username,
  	};
  	message.rid = room._id;
  
  	if (!Match.test(message.msg, String)) {
  		message.msg = '';
  	}
  
  	if (message.ts == null) {
  		message.ts = new Date();
  	}
  
  	if (message.parseUrls !== false) {
  		message.html = message.msg;
  		message = Markdown.code(message);
  
  		const urls = message.html.match(/([A-Za-z]{3,9}):\/\/([-;:&=\+\$,\w]+@{1})?([-A-Za-z0-9\.]+)+:?(\d+)?((\/[-\+=!:~%\/\.@\,\(\)\w]*)?\??([-\+=&!:;%@\/\.\,\w]+)?(?:#([^\s\)]+))?)?/g);
  		if (urls) {
  			message.urls = urls.map((url) => ({ url }));
  		}
  
  		message = Markdown.mountTokensBack(message, false);
  		message.msg = message.html;
  		delete message.html;
  		delete message.tokens;
  	}
  
  	if (message._id && upsert) {
  		const { _id } = message;
  		delete message._id;
  		Messages.upsert({
  			_id,
  			'u._id': message.u._id,
  		}, message);
  		message._id = _id;
  	} else {
  		message._id = Messages.insert(message);
  	}
  
  	return message;
  };
  