/*
	Created by Michael Schuijff <michael@reglobe.nl>
	Copyright Lost Images, The Netherlands
	
	For more information, visit www.michaelschuijff.nl
*/

router.register('/compose', () => {
	router.redirect('/');
});

router.register(['/compose/$type', '/post/$id/edit'], (values) => {
	if (!(values.type == 'post' || values.type == 'video' || values.type == 'repost' || values.type == 'poll')) {
		router.redirect('/');
		return;
	}

	if (!config.user) {
		if (!config.bot) {
			router.redirect('/login', { url: router.getURL() });
		} else {
			router.noIndex();
		}

		return;
	}
	
	let view = createView({
		menuState: 'compose', hideMainTitleBar: true, hideBottomMenu: true, buttons: ['close', 'confirm'], className: 'compose-view'
	});
		
	let progressBar = createElement('div', 'progress-bar');
	view.titleBar.append(progressBar);

	let post;
	
	function fetchPost () {
		view.spinner();
		
		if (values.type == 'repost' && !values.id && !values.post) {
			api.alert(__('Post not found.'), router.back);
			return;
		}
		
		api.get({
			url: '/post/' + (values.id || values.post),
			success: (result) => {
				post = result.post;
				
				if (values.post) {
					if (!post) {
						api.alert(__('You cannot share this post.'), router.back);
						return;
					}
					
					post = { type: 'repost', post: post.post || post };
					
					compose();
				} else {
					if (post && ~post.permissions.indexOf('edit')) {
						compose();
					} else {
						api.alert(__('You cannot edit this post.'), router.back);
					}
				}
			},
			error: () => api.alert(__('Post not found.'), router.back)
		});
	}
	
	let video;
	
	function fetchVideo () {
		view.spinner();
		
		if (!values.file) {
			api.alert(__('Video is missing.'), router.back);
			return;
		}
		
		video = createElement('video');

		let timecodes;
		
		video.addEventListener('canplaythrough', () => {
			if (timecodes) {
				return;
			}
			
			let length = video.duration;
			
			if (length < 5) {
				api.alert(__('This video is too short.'), router.back);
				return;
			}
			
			if (length > 120) {
				api.alert(__('This video exceeds the maximum length of 2 minutes.'), router.back);
				return;
			}
			
			post = { type: 'video', thumbnails: [] };
			
			let canvas = createElement('canvas');
			Object.assign(canvas, { width: 800, height: 800 });
			
			if (video.videoHeight / canvas.height > video.videoWidth / canvas.width) {
				canvas.width = Math.round(video.videoWidth / (video.videoHeight / canvas.height));
			} else {
				canvas.height = Math.round(video.videoHeight / (video.videoWidth / canvas.width));
			}
			
			let ctx = canvas.getContext('2d');
			ctx.fillStyle = '#000000';
			
			video.addEventListener('seeked', () => {
				setTimeout(() => {
					ctx.fillRect(0, 0, canvas.width, canvas.height);
					ctx.drawImage(video, 0, 0, video.videoWidth, video.videoHeight, 0, 0, canvas.width, canvas.height);
					
					canvas.toBlob((blob) => {
						post.thumbnails[post.thumbnails.length] = blob;
						
						if (timecodes.length) {
							video.currentTime = timecodes.shift();
						} else {
							compose();
						}
					});
				}, 150);
			});
			
			timecodes = [length * .25 | 0, length * .5 | 0, length * .75 | 0];
			
			video.currentTime = timecodes.shift();
		});
								
		video.onerror = () => {
			api.alert(__('Unable to open video file.'), router.back);
			api.error('loadVideo', video.error);
		}
		
		video.src = URL.createObjectURL(values.file);
		
		video.load();
	}
		
	let change = false, latitude, longitude, country, images, deleteImages = [], thumbnail, url, map;

	function compose () {
		setTitle();
		
		let form = createElement('form', 'compose-' + post.type);
		form.autocomplete = 'off';
		
		form.oninput = () => change = true;
		
		if (post.thumbnails) {
			let thumbnails = createElement('div', 'thumbnails', createElement('span', null, __('Select a thumbnail for this video')));
			
			for (let blob of post.thumbnails) {
				thumbnail = thumbnail || blob;
				
				let outer = createElement('div', 'thumbnail');
				
				let inner = createElement('div', 'inner');
				Object.assign(inner.style, { paddingBottom: (video.videoHeight / video.videoWidth * 100) + '%' });
				
				preload(URL.createObjectURL(blob), (url) => {
					inner.style.backgroundImage = 'url(' + url + ')';
					view.register('destroy', () => URL.revokeObjectURL(url));
				});
				
				outer.onclick = () => {
					for (let element of thumbnails.children) {
						element.classList.toggle('active', element == outer);
					}
					
					thumbnail = blob;
				}
				
				outer.append(inner);
				
				thumbnails.append(outer);
			}
			
			thumbnails.children[1].className += ' active';
			
			form.append(thumbnails);
			
			change = true;
		}
		
		images = post.images || [];

		let list = createElement('div', 'images');
		
		if (!images.length) {
			list.className += ' hidden';
		}
		
		for (let image of images) {
			let element = createElement('div', 'image');
			
			let inner = createElement('div', 'inner');
			
			preload(image.image, (url) => inner.style.backgroundImage = 'url(' + url + ')');
			
			let button = createElement('button', 'button-delete');
			
			button.onclick = () => {
				api.confirm(__('Are you sure you want to delete this image?'), () => {
					deleteImages[deleteImages.length] = image.id;
					
					element.remove();
					
					let index = images.indexOf(image);
					
					if (~index) {
						images.splice(index, 1);
					}
					
					if (!images.length) {
						list.className += ' hidden';
					}
					
					change = true;
				});
			}
			
			element.append(inner, button);
			
			list.append(element);
		}
		
		form.append(list);
		
		url = post.url || null;
		
		let prevURL = url;
		
		{
			let label = createElement('label');
			
			var textarea = createElement('textarea', 'autofill');
			Object.assign(textarea, { name: 'text', spellcheck: false, value: decodeHTML(post.text || '') });
			
			switch (post.type) {
				case 'post':
					textarea.placeholder = __('What do you want to share?');
					break;
					
				case 'video':
					textarea.placeholder = __('What is this video about?');
					break;

				case 'poll':
					textarea.placeholder = __('What question do you want to ask your followers?');
					break;

				case 'repost':
					textarea.placeholder = __('What do you want to say about this post?');
					break;
			}
			
			textarea.onblur = () => {
				let value = textarea.value.trim().replace(/\r\n/g, "\n")
					, lines = value.split(/[\r\n]/);
					
				if (textarea.nextSibling) {
					textarea.nextSibling.remove();
				}
				
				for (let i = 0; i < lines.length; i ++) {
					lines[i] = lines[i].trim().replace(/\s+/g, ' ');
				}
				
				value = lines.join("\n").replace(/\n{3,}/g, "\n\n");
				
				textarea.value = value;
				
				if (post.type == 'post') {
					detectURL();
				}
				
				if (!value && post.type == 'poll') {
					label.append(createElement('span', 'error', __('a question is required')));
					return;
				}
				
				if (value) {
					value = value.replace(/(?:https?:\/\/)?(?:\w+\.[\w\.]*\w{2,})(?:\/[^\s]*)/, ' ');
					
					let hashtags = value.match(/#([\w_]{2,50})/g) || [];
					
					if (hashtags.length > 10) {
						label.append(createElement('span', 'error', __('you have exceeded the maximum of 10 hashtags')));
						return;
					}
				}
			}
			
			if (post.type == 'post') {
				if (post.url) {
					if (post.id) {
						setTimeout(() => addLinkDetails(post.details || { url: post.url }), 0);
					} else {
						api.get({
							url: '/site-details',
							data: { url: url },
							success: (result) => addLinkDetails(result.details),
							error: () => url = null
						});
					}
				}
				
				textarea.onkeydown = (e) => {
					if (e.which == 13 || e.which == 32) {
						setTimeout(detectURL, 0);
					}
				}
				
				textarea.onpaste = () => {
					setTimeout(detectURL, 0);
				}
			}
			
			label.append(textarea);
			
			form.append(label);
		}
		
		if (post.type == 'repost') {
			form.append(renderPost(post.post));
		}
		
		if (post.type == 'post' || post.type == 'video' || post.type == 'poll') {
			var buttons = createElement('div', 'buttons');
			form.append(buttons);
		}
		
		if (post.type == 'post' || post.type == 'poll') {
			if (values.images) {
				queuedImages();
				
				function queuedImages () {
					if (!values.images.length || images.length == 10) {
						delete values.images;
						return;
					}
					
					addImageBlob(values.images.shift(), null, queuedImages);
				}
				
				change = true;
			}

			{
				let button = createElement('button', 'button', __('Photo'));
				button.tabIndex = -1;
				
				button.onclick = () => {
					let count = images.length;
					
					if (count == 10) {
						api.alert(__('You have reached the maximum of 10 photos.'));
						return;
					}
					
					gallery((images) => {
						let image = images.shift();
						addImageBlob(image, image.lastModified, queuedGalleryImages);
						
						count ++;

						function queuedGalleryImages () {
							if (count == 10) {
								return;
							}
							
							if (images.length) {
								addImageBlob(images.shift(), null, queuedGalleryImages);
								count ++;
							}
						}
					}, true);
				}
				
				buttons.append(button);
			}
						
			if (window.cordova) {
				let button = createElement('button', 'button', __('Camera'));
				button.tabIndex = -1;
				
				button.onclick = () => {
					if (images.length == 10) {
						api.alert(__('You have reached the maximum of 10 photos.'));
						return;
					}

					navigator.camera.getPicture((filename) => {
						resolveLocalFileSystemURL(filename, (fileEntry) => {
							fileEntry.file((file) => {
								let reader = new FileReader;
								
								reader.onload = () => {
									addImageBlob(new Blob([new Uint8Array(reader.result)], { type: file.type }));
								}
								
								reader.readAsArrayBuffer(file);
							});
						});
					}, (error) => {
						api.error('getPicture', error);
					}, {
						sourceType: Camera.PictureSourceType.CAMERA, mediaType: Camera.MediaType.PICTURE,
						destinationType: Camera.DestinationType.FILE_URI, encodingType: Camera.EncodingType.JPEG,
						targetWidth: 1080, targetHeight: 1080, correctOrientation: true
					});
				}
				
				buttons.append(button);
			}
		}
		
		if (post.type == 'post' || post.type == 'video') {
			let hashtags = createElement('div', 'hashtags');
			
			let options = {
				start: [
					{
						tag: 'trainspotting', route: ['gauge', 'stock', 'lineside']
					}, {
						tag: 'lineside', route: ['lineside', 'gauge', 'stock']
					}, {
						tag: 'modelrailway', route: ['models', 'gauge', 'stock', 'lineside']
					}, {
						tag: 'photo', route: ['gauge', 'stock', 'lineside']
					}, {
						tag: 'video', route: ['gauge', 'stock', 'lineside']
					}, {
						tag: 'game', route: ['stock']
					}, {
						tag: 'simulator', route: ['stock']
					}
				],
				models: [
					'modeltrain', 'building', 'scenery', 'h0scale', '00gauge', 'ngauge', '0gauge'
				],
				gauge: [
					'train', 'narrowgauge', 'underground', 'metro', 'subway', 'tram', 'monorail'
				],
				stock: [
					'steam', 'diesel', 'dmu', 'gasturbine', 'electric', 'emu', 'hst', 'shunter'
				],
				lineside: [
					'station', 'signalbox', 'tmd', 'depot', 'roundhouse', 'junction', 'crossing'
				]
			};
			
			let route, index = -1;
			
			function listHashtags () {
				let list;
				
				if (!~index) {
					list = options.start;
				} else {
					list = options[route[index]];
				}
				
				hashtags.innerHTML = '';
				
				if (~index) {
					let button = createElement('button', null, '<');
					button.tabIndex = -1;
					
					button.onclick = () => {
						index --;
						listHashtags();
					}
					
					hashtags.append(button);
				}
				
				for (let item of list) {
					let button = createElement('button');
					button.tabIndex = -1;
					
					let hashtag;
					
					if (~index) {
						hashtag = '#' + item;
					} else {
						hashtag = '#' + item.tag;
					}
					
					button.onclick = () => {
						let value = textarea.value;
						
						if (!value.match(new RegExp(hashtag + '\\b', 'i'))) {
							if (value) {
								if (!/#[\w_]{2,50}\b/.test(value)) {
									value += "\n\n";
								} else {
									value += ' ';
								}
							}
							
							textarea.value = value + hashtag;
						}
						
						if (~index) {
							if (index < route.length - 1) {
								index ++;
							}
						} else {
							route = item.route;
							index = 0;
						}
						
						listHashtags();
					}
					
					button.append(hashtag);

					hashtags.append(button);
				}
				
				if (~index && index + 1 < route.length) {
					let button = createElement('button', null, '>');
					button.tabIndex = -1;
					
					button.onclick = () => {
						index ++;
						listHashtags();
					}
					
					hashtags.append(button);
				}
			}
			
			listHashtags();
			
			form.append(hashtags);
		}
		
		if (post.type == 'post' || post.type == 'video') {
			{
				let text;
				
				if (post.type == 'post') {
					text = __('Date photo taken');
				} else {
					text = __('Date video recorded');
				}
				
				let label = createElement('label', null, createElement('span', null, text));
				
				let input = createElement('input', 'date');
				Object.assign(input, { type: 'text', name: 'date', spellcheck: false });
				
				input.onblur = () => {
					input.value = input.value.trim();
					
					if (input.nextSibling) {
						input.nextSibling.remove();
					}
					
					let value = input.value;
					
					if (!value) {
						return;
					}
					
					if (!isValidDate(value)) {
						label.append(createElement('span', 'error', __('invalid date')));
						return;
					}
					
					input.value = formatDate(value);
					
					let midnight = new Date;
					midnight.setHours(0, 0, 0, 0);
					
					if (+toDate(value) > +midnight) {
						label.append(createElement('span', 'error', __('date cannot be in the future')));
						return;
					}
				}
				
				input.value = formatDate(post.date) || '';
				
				if (!input.value) {
					label.className += ' hidden';
				}
				
				label.append(input);
				
				form.append(label);

				let button = createElement('button', 'button', __('Date'));
				button.tabIndex = -1;
				
				button.onclick = () => {
					if (!input.value) {
						label.classList.toggle('hidden');
						
						if (!label.classList.contains('hidden')) {
							input.focus();
						}

						return;
					}
					
					api.confirm(__('Do you want to remove the date photo taken?'), () => {
						label.classList.add('hidden');
						
						input.value = '';
						
						if (input.nextSibling) {
							input.nextSibling.remove();
						}
					});
				}
					
				buttons.append(button);				
			}
			
			latitude = post.latitude || null, longitude = post.longitude || null, country = post.country || null;
			
			var map = new geoMap({
				latitude: latitude,
				longitude: longitude,
				hidden: true,
				marker: true,
				movable: true,
				gps: true,
				change: () => {
					latitude = map.latitude, longitude = map.longitude;
				}
			});
			
			{
				let button = createElement('button', 'button', __('Location'));
				
				button.onclick = () => {
					if (map.hidden) {
						map.unhide();
						change = true;
						return;
					}
					
					api.confirm(__('Do you want to remove location information?'), () => {
						latitude = null, longitude = null, country = null;
						change = true;
						map.hide();
					});
				}
				
				buttons.append(button);
			}
			
			form.append(map.container);
			
			if (latitude !== null) {
				map.unhide();
			}
		}

		if (post.type == 'poll') {
			if (post.poll) {
				let answers = post.poll.answers;
				
				for (let i = 0, length = answers.length; i < length; i ++) {
					let answer = answers[i];
					
					let text = __('Answer') + ' ' + (i + 1);
					
					let label = createElement('label', null, createElement('span', null, text));
					
					let input = createElement('input', 'answer');
					Object.assign(input, { type: 'text', name: 'answers[]', spellcheck: false, value: answer.answer || '' });
					
					input.onblur = () => {
						input.value = input.value.trim();
						
						if (input.nextSibling) {
							input.nextSibling.remove();
						}
						
						if (!input.value) {
							label.append(createElement('span', 'error', __('this answer is required')));
						}
					}
					
					label.append(input);
					
					form.append(label);
				}
			} else {
				let answers = 4;
				
				for (let i = 0; i < answers; i ++) {
					let text = __('Answer') + ' ' + (i + 1);
					
					if (i > 1) {
						text += ' (' + __('optional') + ')';
					}
					
					let label = createElement('label', null, createElement('span', null, text));
					
					let input = createElement('input', 'answer');
					Object.assign(input, { type: 'text', name: 'answers[]', spellcheck: false });
					
					input.onblur = () => {
						input.value = input.value.trim();
						
						if (input.nextSibling) {
							input.nextSibling.remove();
						}
						
						if (!input.value && i < 2) {
							label.append(createElement('span', 'error', __('this answer is required')));
						}
					}
					
					label.append(input);
					
					form.append(label);
				}
				
				let button = createElement('button', 'button', __('Add answer'));
				
				button.onclick = () => {
					answers ++;

					let label = createElement('label', null, createElement('span', null, __('Answer') + ' ' + answers + ' (' + __('optional') + ')'));
					
					let input = createElement('input', 'answer');
					Object.assign(input, { type: 'text', name: 'answers[]', spellcheck: false });
					
					input.onblur = () => {
						input.value = input.value.trim();
					}
					
					label.append(input);
					
					form.insertBefore(label, button);
					
					if (answers == 10) {
						button.remove();
					}
					
					input.focus();
				}
				
				form.append(button);
			}
			
			{
				let label = createElement('label', null, createElement('span', null, __('How long can people vote for')));
				
				let input = createElement('select');
				input.name = 'poll_duration';
				
				for (let i = 1; i < 8; i ++) {
					let option = createElement('option');
					option.value = i;
					
					if (post.poll && post.poll.duration == i) {
						option.selected = true;
					}
					
					if (i == 1) {
						option.append(__('1 day'));
					} else {
						option.append(__('%d days', i));
					}
					
					input.append(option);
				}
				
				label.append(input);
				
				form.append(label);
			}
		}

		view.content.append(form);
		
		view.hideSpinner();

		setTimeout(() => textarea.focus(), 0);
		
		view.register('destroy', () => {
			for (let image of images) {
				if (image instanceof Blob) {
					URL.revokeObjectURL(image.url);
				}
			}
			
			if (post.type == 'post' || post.type == 'video') {
				map.destroy();
			}
		});
		
		function setTitle () {
			let type = post.type || 'post';
			
			let title;
			
			if (values.id) {
				view.setTitle(__('Edit ' + type));
				return;
			}
			
			switch (type) {
				case 'post':
					view.setTitle(__('Quick post'));
					break;
					
				case 'video':
					view.setTitle(__('Upload video'));
					break;
					
				case 'repost':
					view.setTitle(__('Repost'));
					break;
					
				default:
					view.setTitle(__('Create ' + type));
			}
		}
		
		function detectURL () {
			if (url) {
				return;
			}
			
			let words = textarea.value.split(/\s+/);
			
			for (let word of words) {
				if (word.indexOf('.') < 1 || word[word.length - 1] == '.') {
					continue;
				}
				
				if (~word.indexOf('/') && !~word.indexOf('://') && isValidURL('http://' + word)) {
					word = 'http://' + word;
				}

				if (word == prevURL) {
					break;
				}
				
				if (isValidURL(word)) {
					url = word, prevURL = url;
					
					api.get({
						url: '/site-details',
						data: { url: url },
						success: (result) => addLinkDetails(result.details),
						error: () => url = null
					});
					
					break;
				}
			}
		}
		
		function addLinkDetails (details) {
			let element = createElement('div', 'link-details');
			
			let inner = createElement('div', 'inner');
			
			if (details.image) {
				preload(details.image, (url) => inner.style.backgroundImage = 'url(' + url + ')');
			} else {
				element.className += ' no-image';
			}
			
			element.append(inner);
			
			if (details.title) {
				element.append(createElement('div', 'title', details.title));
			}
			
			try {
				element.append(createElement('div', 'domain', new URL(details.url).host));
			} catch (e) {}
			
			let button = createElement('button', 'button-delete');
			
			button.onclick = () => {
				url = null;
				element.remove();
			}
			
			element.append(button);
			
			textarea.parentNode.after(element);
		}
		
		function addImageBlob (blob, lastModified, callback) {
			if (!(blob instanceof Blob)) {
				return;
			}
			
			loadImage(blob, (image, data) => {
				if (!image || image.type == 'error') {
					if (callback) {
						callback();
					}
					
					return;
				}
				
				if (post.type == 'post') {
					let input = form.querySelector('input[name=date]'), label = input.parentNode;
					
					if (!images.length && !input.value && data.exif) {
						let exif = data.exif.getAll();

						lastModified = exif.DateTimeOriginal || exif.DateTime || lastModified || null;
						
						if (typeof lastModified == 'string') {
							lastModified = lastModified.split(' ')[0].replace(/:/g, '-');
						}
						
						if (typeof lastModified == 'number' || lastModified instanceof Date) {
							lastModified = new Date(lastModified);
						}

						if (lastModified) {
							input.value = formatDate(lastModified) || '';
						}
						
						if (input.value) {
							label.classList.remove('hidden');
						}
						
						let coords = exif.GPSInfo || {};
						
						if ('GPSLatitude' in coords && 'GPSLongitude' in coords) {
							api.confirm(__('Would you like to add the GPS coordinates from this picture to your post?'), () => {
								{
									let value = coords.GPSLatitude.split(/[^\d\w]+/);
									
									latitude = +value[0] + (+value[1] || 0) / 60 + (+value[2] || 0) / 3600;
									
									if (coords.GPSLatitudeRef.toUpperCase() == 'S') {
										latitude *= -1;
									}
									
									latitude = +latitude.toFixed(5);
								}
								
								{
									let value = coords.GPSLongitude.split(/[^\d\w]+/);
									
									longitude = +value[0] + (+value[1] || 0) / 60 + (+value[2] || 0) / 3600;
									
									if (coords.GPSLongitudeRef.toUpperCase() == 'W') {
										longitude *= -1;
									}
									
									longitude = +longitude.toFixed(5);
								}
								
								map.setLocation(latitude, longitude);
								
								map.unhide();
							});
						}
					}
				}
				
				let options = { maxWidth: 1080, maxHeight: 1080, canvas: true, orientation: true };
				
				if (image.width / image.height < .8) {
					options.aspectRatio = .8;
				}
				
				loadImage(blob, (canvas) => {
					canvas.toBlob((blob) => {
						blob.url = URL.createObjectURL(blob);
						
						images[images.length] = blob;
						
						let element = createElement('div', 'image');
						
						let inner = createElement('div', 'inner');
						
						inner.style.backgroundImage = 'url(' + blob.url + ')';
						
						let button = createElement('button', 'button-delete');
						
						button.onclick = () => {
							api.confirm(__('Are you sure you want to delete this image?'), () => {
								element.remove(), URL.revokeObjectURL(blob.url);
								
								let index = images.indexOf(blob);
								
								if (~index) {
									images.splice(index, 1);
								}
								
								list.classList.toggle('hidden', !images.length);
								
								change = true;
							});
						}
						
						element.append(inner, button);
						
						list.append(element);
						
						list.classList.remove('hidden');
						
						change = true;
						
						if (callback) {
							callback();
						}
					}, 'image/jpeg');
				}, options);
			}, { orientation: true, meta: true });
		}
		
		function displayMap () {
			
		}
	}
	
	view.register('load', () => {
		if (values.type == 'repost' || values.id) {
			fetchPost();
		} else if (values.type == 'video') {
			fetchVideo();
		} else {
			post = { type: values.type };
			
			for (let key in values) {
				if (key.substr(0, 5) == 'post[' && key[key.length - 1] == ']') {
					post[key.substr(5, key.length - 6)] = values[key];
				}
			}

			compose();
		}
	});
	view.register('close', () => {
		if (!change) {
			return;
		}
		
		let question;
		
		if (values.id) {
			question = __('Are you sure you want to discard your changes?');
		} else {
			question = __('Are you sure you want to discard this concept?');
		}
		
		api.confirm(question, () => router.back(false));
		
		return false;
	});
	
	view.register('confirm', () => {
		if (view.spinning()) {
			return;
		}
		
		let content = view.content;
		
		if (post.type == 'post') {
			let input = content.querySelector('[name=text]'), label = input.parentNode;
			
			if (!input.value && !images.length && !url && !input.nextSibling) {
				label.append(createElement('span', 'error', __('text or an image is required')));
			}
		} else {
			let elements = content.querySelectorAll('input, textarea');
			
			for (let element of elements) {
				if (element.onblur) {
					element.onblur();
				}
			}
		}

		let error = content.querySelector('input ~ .error, textarea ~ .error');
		
		if (error) {
			let parent = error.parentNode, input = parent.querySelector('input, textarea');
			
			input.focus();
			
			return;
		}
		
		view.spinner();
		
		view.buttons.confirm.disabled = true;
		
		let data = {
			type: post.type, url: url || '', latitude: latitude || '', longitude: longitude || '', country: country || ''
		};
		
		if (post.post) {
			data.repost_id = post.post.id;
		}
		
		for (let image of images) {
			if (image instanceof Blob) {
				if (!data.image) {
					data.image = [];
				}
				
				data.image[data.image.length] = image;
			}
		}
		
		if (deleteImages.length) {
			data.delete_image = deleteImages;
		}
		
		let elements = content.querySelectorAll(':not(.hidden) > [name]');
		
		for (let element of elements) {
			let name = element.name;
			
			if (name.substr(name.length - 2) == '[]') {
				name = name.substr(0, name.length - 2);
				
				if (!data[name]) {
					data[name] = [];
				}
			}
			
			if (element.type == 'checkbox') {
				if (element.checked) {
					data[name] = 'true';
				} else {
					data[name] = '';
				}
				
				continue;
			}
			
			if (Array.isArray(data[name])) {
				data[name][data[name].length] = element.value;
				continue;
			}
			
			if (name == 'date') {
				data[name] = formatDateYMD(element.value) || '';
				continue;
			}
			
			data[name] = element.value;
		}
		
		if (!data.date) {
			data.date = '';
		}
		
		if (!data.location) {
			data.location = '';
		}
		
		if (thumbnail) {
			data.thumbnail = thumbnail;
		}
		
		if (!values.id && values.file) {
			data.video = values.file;
		}
		
		api.post({
			url: '/post' + (values.id ? '/' + values.id : ''),
			data: data,
			success: (result) => {
				let post = result.post;
				
				if (values.id) {
					let elements = document.querySelectorAll('.post-' + values.id);
					
					for (let element of elements) {
						element.replaceWith(renderPost(post));
					}
				}
				
				if (post.post) {
					let elements = document.querySelectorAll('.post-' + post.post.id);
					
					for (let element of elements) {
						if (element.parentNode.classList.contains('post')) {
							element = element.parentNode;
						}
						
						let button = element.querySelector('.button-repost'), sibling = button.nextSibling;
						
						button.value = post.post.repost_count;
						sibling.innerHTML = formatNumber(post.post.repost_count);
					}
				}
				
				if (window.activeView == view) {
					router.back(false);
					popupReview();
				}
			},
			progress: (value) => {
				if (values.type != 'video' || values.id) {
					return;
				}
				
				progressBar.style.width = value + '%';

				if (value == 100) {
					toast(__('The video has been uploaded. You\'ll be notified as soon as the video is published.'));
					
					if (window.activeView == view) {
						if (window.cordova) {
							setTimeout(() => cordova.plugins.AppReview.requestReview(), 1000);
						}

						router.back(false);
					}
				}
			},
			error: (error) => {
				view.hideSpinner();
				api.alert(error);
			},
			complete: () => progressBar.style.width = 0
		});
		
		change = false;
	});	
	
	view.register('destroy', () => {
		if (video) {
			URL.revokeObjectURL(video.src);
		}
	});
	
	return view;
});
