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

router.register(['/', '/posts/$query'], (values) => {
	let query = values.query || '';
	
	if (query && !(query == 'popular' || query == 'trains' || query == 'model-trains' || query == 'narrow-gauge' || query == 'underground' || query == 'games')) {
		router.redirect('/');
		return;
	}
	
	let url = '/';
	
	if (query) {
		url += 'posts/' + query;
	}
	
	let title;
	
	switch (query) {
		case 'popular':
			title = __('Popular posts');
			break;
			
		case 'trains':
			title = __('Train posts');
			break;

		case 'model-trains':
			title = __('Model train posts');
			break;

		case 'narrow-gauge':
			title = __('Narrow gauge posts');
			break;

		case 'underground':
			title = __('Underground posts');
			break;

		case 'games':
			title = __('Games posts');
			break;

		default:
			if (config.user) {
				title = __('Personalized timeline');
			} else {
				title = __('Guest timeline');
			}
	}
	
	let view = createView({
		menuState: 'home', analyticsTitle: title, urls: [url], spinner: true, pullToRefresh: true, className: 'posts-view'
	});
	
	let more = createElement('button', 'hidden', createElement('span', 'uppercase', __('New posts')));

	if (config.user) {
		let items = [
			{
				text: __('Home'),
				href: '/'
			}, {
				text: __('Popular'),
				href: '/posts/popular'
			}, {
				text: __('Trains'),
				href: '/posts/trains'
			}, {
				text: __('Model trains'),
				href: '/posts/model-trains'
			}, {
				text: __('Narrow gauge'),
				href: '/posts/narrow-gauge'
			}, {
				text: __('Underground'),
				href: '/posts/underground'
			}, {
				text: __('Games'),
				href: '/posts/games'
			}
		];
		
		let menu = createElement('div', 'timeline-menu');
		
		let inner = createElement('ul', 'inner');
		
		for (let item of items) {
			let element = createElement('li');
			
			let link = createElement('a', 'uppercase', item.text);
			link.href = item.href;
			
			if (item.href == url) {
				link.className += ' active';
			}
			
			element.append(link);
			
			inner.append(element);
		}
		
		let element = createElement('li');
		
		let button = createElement('button', null, createElement('span', 'uppercase', __('More')));
		
		button.onclick = (e) => {
			e.stopPropagation();
			
			let index = inner.querySelectorAll('li:not(.hidden)').length;
			contextMenu(button, items.slice(index));
		}
		
		element.append(button);
		
		inner.append(element);
		
		view.register('load resume resize', () => {
			let elements = inner.querySelectorAll('li.hidden');
			
			for (let element of elements) {
				element.classList.remove('hidden');
			}
			
			let element = button.parentNode;
			element.className = 'hidden';
			
			const width = document.body.clientWidth;
			
			if (inner.scrollWidth > width) {
				element.className = '';
				element = element.previousSibling;
				
				while (element && inner.scrollWidth > width) {
					element.className = 'hidden';
					element = element.previousSibling;
				}
			}
		});
		
		more.onclick = () => {
			more.className = 'hidden';
			
			view.scrollTop = 0;
			view.updateScroll();
		}

		view.register('scroll', () => {
			if (view.scrollTop < 10) {
				more.className = 'hidden';
			}
		});

		menu.append(inner, more);

		view.content.before(menu);
	}
	
	let timeline = createElement('div', 'timeline');
	
	view.content.append(timeline);
	
	let reqBefore, firstPost, timer;
	
	function fetchPostsBefore () {
		clearTimeout(timer);
		
		refreshPostsCount(timeline);
					
		reqBefore = api.get({
			url: '/posts/' + (query || 'timeline'),
			data: { since_id: firstPost, suggestions: fetchSuggestions() || null },
			success: (result) => {
				let fragment = document.createDocumentFragment();

				let posts = result.posts;
				
				for (let post of posts) {
					fragment.append(renderPost(post));
				}
									
				let scrollHeight = document.documentElement.scrollHeight;
				
				if (timeline.firstChild && timeline.firstChild.className == 'usage-hint') {
					timeline.children[1].before(fragment);
				} else {
					timeline.prepend(fragment);
				}
				
				setTimeout(view.videoElements, 0);
				
				if (posts.length) {
					if (view.scrollTop > 10) {
						view.scrollTop += document.documentElement.scrollHeight - scrollHeight;
						
						if (config.user) {
							more.className = 'button-more';
						}

						view.updateScroll();
					}
				
					firstPost = posts[0].id;
				}

				if (result.suggestions) {
					renderSuggestions(result.suggestions);
				}
				
				if (result.more) {
					setTimeout(fetchPostsBefore, 0);
				}
			},
			complete: () => {
				reqBefore = null;
				
				if (config.user) {
					timer = setTimeout(() => {
						reqBefore || fetchPostsBefore();
					}, 20000);
				}
			}
		});
	}
	
	function fetchSuggestions () {
		if (!suggestions) {
			return true;
		}
		
		if (timeline.children.length < 3) {
			return false;
		}

		let rect = suggestions.getBoundingClientRect();
		
		if (rect.top < window.innerHeight) {
			return false;
		}
		
		for (let i = 0; i < 3; i ++) {
			if (timeline.children[i] == suggestions) {
				return false;
			}
		}
		
		return true;
	}
	
	let reqAfter, lastPost;

	function fetchPostsAfter () {
		reqAfter = api.get({
			url: '/posts/' + (query || 'timeline'),
			data: { until_id: lastPost },
			success: (result) => {
				let fragment = document.createDocumentFragment();
				
				if (!lastPost && !query) {
					timeline.append(renderHint());
				}
				
				let posts = result.posts;

				for (let post of posts) {
					fragment.append(renderPost(post));
				}
				
				if (posts.length) {
					firstPost = firstPost || posts[0].id;
					lastPost = posts[posts.length - 1].id;
				}
				
				timeline.append(fragment);					

				if (result.suggestions) {
					renderSuggestions(result.suggestions);
				}
				
				setTimeout(view.videoElements, 0);

				if (result.more) {
					view.enableInfiniteScrolling();
					
					if (view == window.activeView && view.content.offsetHeight < window.innerHeight) {
						setTimeout(fetchPostsAfter, 0);
					}
				} else {
					view.disableInfiniteScrolling();
				}
				
				if (!config.user) {
					config.session = result.session || null;
				}
			},
			complete: () => {
				reqAfter = null;
				
				view.hideSpinner();
				view.revertPullToRefresh();
			}
		});
	}
	
	view.register('load', () => {
		fetchPostsAfter();
		
		if (!config.user) {
			return;
		}

		timer = setTimeout(() => {
			reqBefore || fetchPostsBefore();
		}, 20000);
	});
	
	view.register('pause destroy', () => {
		clearTimeout(timer);
		
		if (reqBefore) {
			reqBefore.abort();
		}
		
		if (reqAfter) {
			reqAfter.abort();
		}
		
		reqBefore = null, reqAfter = null;
	});
	
	view.register('resume', () => {
		if (!config.user) {
			return;
		}
		
		if (lastPost) {
			fetchPostsBefore();
		} else {
			fetchPostsAfter();
		}
	});
	
	view.register('refresh', () => {
		firstPost = null, lastPost = null;
		
		if (config.user) {
			clearTimeout(timer);
			
			timer = setTimeout(() => {
				reqBefore || fetchPostsBefore();
			}, 20000);
		}
		
		if (reqBefore) {
			reqBefore.abort();
		}
		
		if (reqAfter) {
			reqAfter.abort();
		}
		
		reqBefore = null, reqAfter = null;
		
		view.spinner();
		
		timeline.innerHTML = '';
		
		fetchPostsAfter();
	});		
	
	view.register('infinite-scroll', () => {
		reqAfter || fetchPostsAfter();
	});	
	
	function renderHint () {
		let user = config.user;
		
		if (!user && !window.cordova) {
			return hint({
				title: __('Download Train Siding'),
				message: __('Download the Train Siding app for free and join our online community today.'),
				label: __('Download the app'),
				href: '/download',
				expires: 60
			});			
		}
		
		if (!user) {
			return hint({
				title: __('Join Train Siding'),
				message: __('Join our online community and get access to thousands of railway photos and videos.'),
				label: __('Join the conversation'),
				href: '/login',
				expires: 60
			});
		}
		
		if ((user.service_name && !user.email) || (user.email && ~user.email.toLowerCase().indexOf('@privaterelay.appleid.com'))) {
			return hint({
				title: __('Add your email address'),
				message: __('Add your email address to your profile.'),
				label: __('Add email address'),
				href: '/profile/edit',
				expires: 24 * 3600
			});
		}
		
		if (Math.max(user.follower_count, user.following_count) < 25) {
			return hint({
				title: __('Discover Train Siding'),
				message: __('Follow others who share photos of the trains, model railways and games you love.'),
				label: __('Follow users'),
				href: '/search/users',
				expires: 24 * 3600
			});
		}
		
		if (user.follower_count < 50) {
			return hint({
				title: __('Alert settings'),
				message: __('Receiving too many notifications? Choose which alerts and emails you want to receive from us.'),
				label: __('Edit your alert settings'),
				href: '/alerts/settings',
				expires: 5 * 24 * 3600
			});
		}
		
		if (~user.avatar.indexOf('default.png')) {
			return hint({
				title: __('Add a profile picture'),
				message: __('Why not add a photo to your profile? It will help others recognize you and your messages.'),
				label: __('Add picture'),
				href: '/profile/edit',
				expires: 24 * 3600
			});
		} 
		
		if (!user.biography) {
			return hint({
				title: __('Add a biography'),
				message: __('Add a biography to your profile and tell others about yourself and your interests.'),
				label: __('Edit my profile'),
				href: '/profile/edit',
				expires: 24 * 3600
			});
		}
		
		if (!user.youtube) {
			return hint({
				title: __('Link your YouTube channel'),
				message: __('Link your YouTube channel and automatically publish any newly uploaded YouTube video to your Train Siding profile.'),
				label: __('Add your YouTube channel'),
				href: '/settings/youtube',
				expires: 14 * 24 * 3600
			});
		}
		
		function hint (values) {
			let option = options.get('hide-hint');
			
			if (option) {
				option = option.split(',');
				
				if (values.title == option[0] && Date.now() < +option[1] * 1000) {
					return document.createDocumentFragment();
				}
			}
			
			options.set('hide-hint', values.title + ',' + ((Date.now() / 1000 | 0) + values.expires));
			
			let container = createElement('div', 'usage-hint');
			
			let content = createElement('div', 'content');
			
			let close = createElement('button', 'close');
			
			close.onclick = () => container.remove();
			
			content.append(close);
			
			content.append(createElement('h2', 'uppercase', values.title), createElement('p', null, values.message));
			
			let link = createElement('a', 'uppercase', values.label);
			link.href = values.href;
			
			link.onclick = () => container.remove();
			
			content.append(link);
			
			container.append(content);
			
			return container;
		}
		
		return document.createDocumentFragment();
	}

	let suggestions;

	function renderSuggestions (users) {
		if (suggestions && suggestions.parentNode) {
			let rect = suggestions.getBoundingClientRect();
			
			if (rect.top < window.innerHeight) {
				return false;
			}
			
			suggestions.remove();
		}
		
		suggestions = createElement('div', 'suggestions');
		
		let inner = createElement('div', 'inner feature-follow');
		
		suggestions.append(inner, createElement('h2', 'uppercase', __('Our suggestions for you')));
		
		inner.onclick = (e) => {
			let target = e.target;
			
			if (!target.classList.contains('button-hide')) {
				return;
			}
			
			let userID = target.parentNode.className.match(/user-(\S+)/)[1], username = getUserName(userID);
			
			api.post({
				url: '/user/' + userID + '/hide',
				error: false
			});
			
			toast(__('%s hidden from your suggestions', username));
			target.parentNode.remove();
		}
		
		if (navigator.share && config.user) {
			let invite = createElement('div', 'invite');
			
			let link = createElement('a');
			
			if (config.user.username) {
				link.href = config.url + '/username/' + config.user.username;
			} else {
				link.href = config.url + '/user/' + config.user.id;
			}
			
			link.append(createElement('span', 'avatar'), __('Invite your friends'));
			
			invite.append(link);
			
			let button = createElement('button', 'button-invite', createElement('span', 'uppercase', __('Invite')));
			
			button.onclick = (e) => {
				e.preventDefault();
				e.stopPropagation();
				
				navigator.share({ text: __('Join me on Train Siding!'), url: link.href });
				
				analytics.push('share', { item_id: link.href });
			}
			
			link.onclick = button.onclick;
			
			invite.append(button);
			
			inner.append(invite);
		}

		for (let user of users) {
			inner.append(renderUser(user, ['hide', 'follow', 'pending', 'unfollow']));
		}
		
		timeline.insertBefore(suggestions, timeline.children[2]);
	}
	
	return view;
});

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

		return;
	}
	
	let latlng = (values.latlng || '').match(/^(-?\d{1,2}(?:\.\d+)?),(-?[01]?\d{1,2}(?:\.\d+)?)$/);
	
	if (!latlng) {
		toast(__('Unknown location.'));
		router.back();
		
		return;
	}
	
	let latitude = +latlng[1], longitude = +latlng[2];
	
	latlng = latitude + ',' + longitude;
	
	let title = values.location || '', url = '/location?latlng=' + latlng;
	
	let view = createView({
		titleBar: title,  hideMainTitleBar: true, hideBottomMenu: true, buttons: ['close'], urls: [url], className: 'location-view', spinner: true, pullToRefresh: true
	});
	
	let map = new geoMap({
		latitude: latitude, longitude: longitude, zoom: 15, marker: true, movable: false, gps: false,
		click: () => router.visit('https://www.google.com/maps/search/?api=1&query=' + latlng)
	});
	
	view.content.append(map.container);
	
	let timeline = createElement('div', 'timeline');
	
	view.content.append(timeline);
	
	let req, lastPost;
	
	function fetchPosts () {
		req = api.get({
			url: '/search/posts',
			data: { q: 'near:' + latlng + ' distance:3km', until_id: lastPost },
			success: (result) => {
				let posts = result.posts || [];
				
				for (let post of posts) {
					timeline.append(renderPost(post));
				}
				
				if (posts.length) {
					if (!values.location) {
						values.location = posts[0].location;
						view.setTitle(values.location);
					}
					
					lastPost = posts[posts.length - 1].id;
				}
				
				view.hideSpinner();
				
				map.resize();

				if (result.more) {
					view.enableInfiniteScrolling();
					
					if (view.content.offsetHeight < window.innerHeight) {
						setTimeout(fetchPosts, 0);
					}
				} else {
					view.disableInfiniteScrolling();
				}
			},
			complete: () => {
				req = null;
				
				if (!values.location) {
					view.setTitle(__('Location'));
				}

				view.revertPullToRefresh();
			}
		});
	}

	view.register('load', () => {
		fetchPosts();
	});
	
	view.register('refresh', () => {
		if (req) {
			req.abort();
		}
		
		req = null;
		
		view.spinner();
		timeline.innerHTML = '';
		
		lastPost = null;
		fetchPosts();
	});
	
	view.register('pause', () => {
		if (req) {
			req.abort();
		}
		
		req = null;
	});
	
	view.register('resume', () => {
		map.resize();
		refreshPostsCount(timeline);
	});
	
	view.register('infinite-scroll', () => {
		req || fetchPosts();
	});
	
	view.register('destroy', () => {
		map.destroy();
	});

	return view;	
});
