// ==UserScript==
// @name        2chen_live_filter
// @description
// @version     1
// @match       https://*.2chen.org/*
// @match       https://*.2chen.moe/*
// ==/UserScript==

(function () {
	'use strict';
	var relative_timestamps = localStorage.relativeTime === 'true',
	hide_recursive = localStorage.hideRecursively === 'true',
	filter_active = localStorage.filterPosts === 'on',
	filter_renamed = false,
//	filter_recursive = hide_recursive,
	filter_recursive = false,
	filter_insensitive = true,
	filter_match_flags = filter_insensitive ? 'i' : '',
	files_tested = new Set(),
	posts_ignore = new Set(),
	posts_hidden = new Set(),
	posts_filtered = new Set(),
	posts_watching = new Set(),
	hash_filters = [],
	file_filters = [],
	text_filters = [],
	file_filters_active = false,
	text_filters_active = false;
	if (filter_active) {
		localStorage.customFilterText.split(/[\r\n]+/).forEach(function (filter) {
			if (filter.length === 0) return;
			if (filter.charAt(0) === '#') return;
			if (filter.startsWith('hash:')) {
				hash_filters.push(filter.substr('hash:'.length));
			} else if (filter.startsWith('filename:')) {
				file_filters.push(new RegExp(filter.substr('filename:'.length), filter_match_flags));
			} else if (filter.startsWith('text:')) {
				text_filters.push(new RegExp(filter.substr('text:'.length), filter_match_flags));
			} else {
				text_filters.push(new RegExp(filter, filter_match_flags));
			}
		});
		file_filters_active = hash_filters.length + file_filters.length + +filter_renamed;
		text_filters_active = text_filters.length;
		filter_active = file_filters_active + text_filters_active;
	}
	if (filter_active || hide_recursive) {
		var threads = document.querySelector('section#thread-container');
		threads.querySelectorAll('article').forEach(test_node);
		new MutationObserver(function (mutations) {
			mutations.forEach(function (mutation) {
				if (mutation.type === 'childList' && mutation.target.tagName === 'SECTION' && mutation.target.id === 'thread-container') {
					mutation.addedNodes.forEach(test_node);
				} else if (mutation.type === 'attributes' && mutation.target.tagName === 'ARTICLE') {
					test_node(mutation.target);
				}
			});
		}).observe(threads, {attributes: true, childList: true, subtree: true, attributeFilter: ['class']});
	}
	function test_node(post) {
		if (posts_ignore.has(post.id) || post.classList.contains('reply-form')) {
			posts_ignore.add(post.id);
		} else if (hide_recursive && (posts_hidden.has(post.id) || post.classList.contains('hidden'))) {
			posts_hidden.add(post.id);
		} else if (filter_active && (posts_filtered.has(post.id) || post.classList.contains('filtered'))) {
			posts_filtered.add(post.id);
		} else if (!test_post(post) && !posts_watching.has(post.id) && post.classList.contains('editing')) {
			posts_watching.add(post.id);
			watch_post(post);
		}
	}
	function watch_post(post) {
//		console.log('+' + post.id);
		new MutationObserver(function (mutations, observer) {
			if (test_post(post) || !post.classList.contains('editing')) {
//				console.log('-' + post.id);
				observer.disconnect();
			}
		}).observe(post, {attributes: true, childList: true, subtree: true, attributeFilter: ['class']});
	}
	function test_post(post) {
		if (hide_recursive && test_post_hide(post)) {
			return true;
		} else {
			return filter_active && test_post_filter(post);
		}
	}
	function test_post_filter(post) {
		if (posts_filtered.has(post.id)) return true;
		var link = file_filters_active && !files_tested.has(post.id) ? post.querySelector('figcaption a[data-hash]') : false,
		filter = false,
		filter_text = '';
		if (link) {
			var hash = link.getAttribute('data-hash');
			hash_filters.forEach(function (hash_filter) {
				if (filter) return;
				if (filter = hash_filter === hash) {
					filter_text = 'hash:' + hash_filter;
				}
			});
			var file = link.innerText;
			file_filters.forEach(function (file_filter) {
				if (filter) return;
				if (filter = file_filter.test(file)) {
					filter_text = 'filename:' + file_filter.toString();
				}
			});
			var file_time_stamp;
			if (!filter && filter_renamed && (file_time_stamp = file.match(/^(\d{13})\.\w+$/))) {
				var post_time_stamp, post_time_tag = post.querySelector('header time');
				if (relative_timestamps && post_time_tag.title !== '') { // initial page load
					post_time_stamp = post_time_tag.title;
				} else {
					post_time_stamp = post_time_tag.innerText;
				}
				var post_time = (new Date(post_time_stamp)).getTime()-(new Date()).getTimezoneOffset();
				var file_time = +file_time_stamp[1];
				if (filter = (file_time >= (post_time-300000)) && (file_time <= (post_time+300000))) {
					filter_text = 'renamed_files';
				}
				if (!filter && (filter = (file_time >= (post_time+3300000)) && (file_time <= (post_time+3900000)))) { // initial page load
//					filter_text = 'renamed_files (dst)';
					filter_text = 'renamed_files';
				}
			}
			files_tested.add(post.id);
		}
		if (!filter && text_filters_active) {
			var text = post.querySelector('div.post-container').innerText;
			text_filters.forEach(function (text_filter) {
				if (filter) return;
				if (filter = text_filter.test(text)) {
					filter_text = 'text:' + text_filter.toString();
				}
			});
		}
		if (!filter && filter_recursive) {
			post.querySelectorAll('div.post-container blockquote a.post-link[data-id]').forEach(function (post_link) {
				if (filter) return;
				if (filter = posts_filtered.has('p' + post_link.getAttribute('data-id'))) {
					filter_text = 'reply:>>' + post_link.getAttribute('data-id');
				}
			});
		}
		if (filter) {
			posts_filtered.add(post.id);
			post.classList.add('filtered');
			var stub = document.createElement('div');
			stub.innerText = 'Post filtered (' + filter_text + ')';
			stub.className = 'filter-stub';
			stub.onclick = function showFilteredPost() {
				var post = this.parentNode;
				if (post.classList.contains('filtered')) {
					post.classList.remove('filtered');
					post.classList.add('filtered-shown');
				} else {
					post.classList.remove('filtered-shown');
					post.classList.add('filtered');
				}
			};
			post.append(stub);
		}
		return filter;
	}
	function test_post_hide(post) {
		if (posts_hidden.has(post.id)) return true;
		var hide = false;
		post.querySelectorAll('div.post-container blockquote a.post-link[data-id]').forEach(function (post_link) {
			if (hide) return;
			hide = posts_hidden.has('p' + post_link.getAttribute('data-id'));
		});
		if (hide) {
			posts_hidden.add(post.id);
			post.classList.add('hidden');
		}
		return hide;
	}
})();