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

(function () {
	let manualScrolling = false;
		
	window.createView = function (options) {
		options = options || {};
		
		let container = createElement('div', 'view active');
			
		if (options.className) {
			container.className += ' ' + options.className;
		}
		
		if (options.hideMainTitleBar) {
			container.className += ' hide-main-title-bar';
		}
		
		if (options.hideBottomMenu) {
			container.className += ' hide-bottom-menu';
		}
		
		let content = createElement('div', 'content'), spinner = createElement('div', 'spinner');
			
		if (options.spinner) {
			container.className += ' spinner';
		}
		
		let titleBar = createElement('div', 'title-bar');
		container.append(titleBar, content, spinner);

		let view = {
			container: container, titleBar: titleBar, content: content
		};

		view.spinner = function () {
			container.classList.add('spinner');
		}
		
		view.hideSpinner = function () {
			container.classList.remove('spinner');
		}
		
		view.spinning = function () {
			return container.classList.contains('spinner');
		}

		let events = {};
		
		view.register = function (event, callback) {
			event.split(' ').forEach((event) => {
				if (!events[event]) {
					events[event] = [];
				}
				
				events[event][events[event].length] = callback;
			});
		}
				
		view.trigger = function (event, value) {
			if (!events[event]) {
				return true;
			}
			
			for (let callback of events[event]) {
				if (callback(value) === false) {
					return false;
				}
			}
			
			return true;
		}
		
		view.destroy = function () {
			view.trigger('destroy');
			container.remove();
		}
		
		if (options.scrollBottom) {
			view.scrollBottom = 0;
		}
		
		view.scrollTop = 0;
		
		view.updateScroll = function () {
			if (window.activeView != view) {
				return;
			}
			
			manualScrolling = true;
			
			if ('scrollBottom' in view) {
				window.scrollTo(0, document.documentElement.scrollHeight - window.innerHeight - view.scrollBottom);
			} else {
				window.scrollTo(0, view.scrollTop);
			}
			
			view.calculateScroll();
			
			manualScrolling = false;
		}
		
		view.calculateScroll = function () {
			if (window.activeView != view) {
				return;
			}

			if ('scrollBottom' in view) {
				let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
				view.scrollBottom = document.documentElement.scrollHeight - window.innerHeight - scrollTop;
			}
			
			view.scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
		}

		view.enableInfiniteScrolling = function () {
			view.infiniteScrolling = true;
			container.classList.add('infinite-scrolling');
		}
		
		view.disableInfiniteScrolling = function () {
			view.infiniteScrolling = false;
			container.classList.remove('infinite-scrolling');
		}
		
		if (view.infiniteScrolling = !!options.infiniteScrolling) {
			container.className += ' infinite-scrolling';
		}

		if (options.pullToRefresh) {
			let element = createElement('div', 'pull-to-refresh');
			
			let x, y, top, threshold, state, timer;

			view.revertPullToRefresh = function () {
				element.className = 'pull-to-refresh revert';
				element.style.top = null;
				
				state = 'reverted';
			}

			view.resetPullToRefresh = function () {
				element.className = 'pull-to-refresh';
				element.style.top = null;
				
				state = 'reset';
			}
			
			view.register('resume', view.resetPullToRefresh);
			
			container.addEventListener('touchstart', (e) => {
				if (e.touches.length > 1 || state == 'released' || state == 'pulled' || e.target.matches('textarea')) {
					state = 'cancelled';
					return;
				}
				
				if (container.classList.contains('spinner')) {
					state = 'cancelled';
				} else {
					state = 'init';
				}
	
				x = e.touches[0].pageX, y = e.touches[0].pageY, top = 0, threshold = 130;

				element.className = 'pull-to-refresh';
			}, { passive: false });
			
			container.addEventListener('touchmove', (e) => {
				if (e.touches.length > 1 || state == 'released' || state == 'cancelled') {
					return;
				}
				
				let touchX = e.touches[0].pageX, touchY = e.touches[0].pageY;
				
				if (container.classList.contains('spinner')) {
					state = 'cancelled';
				} else if (state == 'init') {
					if (Math.abs(x - touchX) > Math.abs(y - touchY)) {
						state == 'cancelled';
					} else if (Math.abs(y - touchY) > Math.abs(x - touchX)) {
						state = 'pulling';
					}
				}
				
				if (state == 'cancelled') {
					return;
				}
				
				top = Math.max(0, top + (touchY - y) / 2);
				
				x = touchX, y = touchY;
				
				if (view.scrollTop - top < 0) {
					top -= view.scrollTop;
					
					view.scrollTop = 0;
					window.scrollTo(0, 0);
				}
				
				if (!top || view.scrollTop) {
					if (state == 'pulled') {
						state = 'pulling';
					}
					
					top = 0;
					element.style.top = null;
				} else {
					clearTimeout(timer);
					e.stopPropagation();
					
					if (e.cancelable) {
						e.preventDefault();
					}
					
					if (top > threshold) {
						state = 'pulled';
					}
					
					element.style.top = top + 'px';
				}
			}, { passive: false });

			function completePullToRefresh () {
				clearTimeout(timer);
				
				timer = setTimeout(view.revertPullToRefresh, 5000);
				
				view.trigger('refresh');
				state = 'released';
				
				element.classList.add('pulled');
				element.style.top = null;
			}
			
			function pullTouchEnd (e) {
				if (state == 'pulled') {
					completePullToRefresh();
				} else if (!(state == 'init' || state == 'released')) {
					view.revertPullToRefresh();
				}
			}

			container.addEventListener('touchend', pullTouchEnd);
			container.addEventListener('touchcancel', pullTouchEnd);
			
			container.append(element);
			view.pullToRefresh = element;
		}
		
		view.titleBar.innerHTML = '<div class="label uppercase">' + encodeHTML(options.titleBar || '') + '</div>';
		
		view.buttons = {};
		
		if (options.titleBar || (options.buttons && options.buttons.length)) {
			container.className += ' has-title-bar';
			
			view.createButton = function (trigger) {
				let button = createElement('button', 'button-' + trigger);
				
				button.addEventListener('click', (e) => {
					if (trigger == 'close') {
						if (view.trigger(trigger)) {
							router.back(false);
						}
					} else {
						view.trigger(trigger);
					}
				});
				
				view.titleBar.append(button);
				
				return button;
			}
			
			if (options.buttons) {
				options.buttons.forEach((button) => view.buttons[button] = view.createButton(button));
			}
		}
		
		view.setTitle = function (title) {
			let label = view.titleBar.firstChild;
			
			if (label && ~label.className.indexOf('label')) {
				label.innerHTML = encodeHTML(title);
			}
		}
		
		view.getTitle = function () {
			if (options.analyticsTitle) {
				return options.analyticsTitle;
			}
			
			let label = view.titleBar.firstChild;
			
			if (!label) {
				return null;
			}
			
			return label.textContent;
		}
				
		if (options.menuState) {
			view.menuState = options.menuState;
		}
		
		view.videoElements = function () {
			if (!window.activeView) {
				return;
			}
			
			if (activeView != view) {
				return;
			}
			
			let elements = content.querySelectorAll('.video');
			
			for (let element of elements) {
				let rect = element.getBoundingClientRect();
				
				let visible = false;
				
				if (rect.width) {
					visible = rect.top <= window.innerHeight && rect.bottom >= 0;
				}
				
				if (element.youtube) {
					let iframe = element.querySelector('iframe');
					
					if (iframe && !visible) {
						iframe.remove();
					}
					
					if (!iframe && visible) {
						let embed = 'https://www.youtube-nocookie.com/embed/' + element.youtube + '?modestbranding=1&fs=0&hl=' + config.language;
						
						let iframe = createElement('iframe');
						Object.assign(iframe, { src: embed, allowtransparency: true });
						
						element.firstChild.append(iframe);
					}
				} else if (!visible) {
					let video = element.querySelector('video');
					video.paused || video.pause();
				}
			}
		}

		let timer;

		view.register('scroll', () => {
			clearTimeout(timer);
			timer = setTimeout(view.videoElements, 100);
		});

		view.register('pause', () => {
			let elements = container.querySelectorAll('.menu-active');
			
			for (let element of elements) {
				element.classList.remove('menu-active');
			}

			clearTimeout(timer);

			let iframes = content.querySelectorAll('.video iframe');
			
			for (let iframe of iframes) {
				iframe.remove();
			}
			
			let videos = content.querySelectorAll('video');
			
			for (let video of videos) {
				video.paused || video.pause();
			}
		});
		
		view.register('resume', view.videoElements);
		
		view.addURL = function (url) {
			view.urls = view.urls || [];
			view.urls[view.urls.length] = url;
			
			cache.set(view);
		}
		
		view.removeURL = function (url) {
			if (!view.urls) {
				return;
			}
			
			let index = view.urls.indexOf(url);
			
			if (~index) {
				view.urls.splice(index, 1);
			}
		}
		
		if (options.urls) {
			for (let url of options.urls) {
				view.addURL(url);
			}
			
			cache.set(view);
		}

		return view;
	}

	window.loadView = function (view, trigger) {
		if (view == window.activeView) {
			return;
		}
		
		view.loading = true;
		
		let container = view.container;
		
		container.classList.add('active');
		mainTitleBar.before(container);
		
		for (let element of navMenus) {
			let elements = element.querySelectorAll('.menu-item');
			
			for (let element of elements) {
				let state = false;
				
				if (view.menuState) {
					state = element.classList.contains('menu-' + view.menuState);
				}
				
				element.classList.toggle('active', state);
			}
		}
		
		if (window.activeView) {
			activeView.lastUsed = Date.now();
			
			let container = activeView.container, urls = activeView.urls;

			if (urls && urls.length) {
				activeView.trigger('pause');
				container.classList.remove('active');
			} else {
				activeView.destroy();
				container.remove();
			}
			
			readableDatetime();
			
			setTimeout(cache.expire, 0);
		}
		
		window.activeView = view;
		
		view.loading = false;

		view.updateScroll();
		
		view.trigger(trigger);
	}

	window.renderDatetime = function (datetime) {
		let element = createElement('time', null, formatDateLocal(datetime, 'readable', __('ago')));
		
		Object.assign(element, { datetime: datetime, title: formatDateLocal(datetime, 'readable-date') });
		
		return element;
	}

	window.readableDatetime = function () {
		let elements = document.querySelectorAll('time');
		
		for (let element of elements) {
			Object.assign(element, {
				title: formatDateLocal(element.datetime, 'readable-date'),
				innerHTML: encodeHTML(formatDateLocal(element.datetime, 'readable', __('ago')))
			});
		}
	}
	
	setInterval(readableDatetime, 15000);	

	let timer;
			
	document.addEventListener('scroll', () => {
		if (!manualScrolling && !(window.activeView && activeView.loading)) {
			window.scrolling = true;
			
			clearTimeout(timer);
			
			timer = setTimeout(() => {
				window.scrolling = false
			}, 0);
			
			if (!window.activeView) {
				return;
			}
			
			activeView.calculateScroll();
			
			activeView.trigger('scroll');
			
			let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
			
			if (!activeView.infiniteScrolling) {
				return;
			}
			
			let scrollHeight = activeView.content.offsetHeight - Math.max(window.innerWidth, window.innerHeight) * 2;
			
			if (scrollTop + window.innerHeight > scrollHeight) {
				activeView.trigger('infinite-scroll');
			}
		}
	});

	window.addEventListener('resize', () => {
		if (window.activeView) {
			activeView.trigger('resize');
		}
	});

	document.fonts && document.fonts.ready.then(() => {
		if (window.activeView) {
			activeView.trigger('resize');
		}
	});

	document.addEventListener('paste', (e) => {
		if (window.activeView) {
			activeView.trigger('paste', e);
		}
	});
})();
