import {LitElement, html, unsafeHTML, until} from './lit-all.min.js';
import * as tfrpc from '/static/tfrpc.js';
import {styles} from './tf-styles.js';

class TfNewsElement extends LitElement {
	static get properties() {
		return {
			whoami: {type: String},
			users: {type: Object},
			messages: {type: Array},
			following: {type: Array},
			drafts: {type: Object},
			expanded: {type: Object},
		};
	}

	static styles = styles;

	constructor() {
		super();
		let self = this;
		this.whoami = null;
		this.users = {};
		this.messages = [];
		this.following = [];
		this.drafts = {};
		this.expanded = {};
	}

	process_messages(messages) {
		let self = this;
		let messages_by_id = {};

		console.log('processing', messages.length, 'messages');

		function ensure_message(id) {
			let found = messages_by_id[id];
			if (found) {
				return found;
			} else {
				let added = {
					id: id,
					placeholder: true,
					content: '"placeholder"',
					parent_message: undefined,
					child_messages: [],
					votes: [],
				};
				messages_by_id[id] = added;
				return added;
			}
		}

		function link_message(message) {
			if (message.content.type === 'vote') {
				let parent = ensure_message(message.content.vote.link);
				if (!parent.votes) {
					parent.votes = [];
				}
				parent.votes.push(message);
				message.parent_message = message.content.vote.link;
			} else if (message.content.type == 'post') {
				if (message.content.root) {
					if (typeof(message.content.root) === 'string') {
						let m = ensure_message(message.content.root);
						if (!m.child_messages) {
							m.child_messages = [];
						}
						m.child_messages.push(message);
						message.parent_message = message.content.root;
					} else {
						let m = ensure_message(message.content.root[0]);
						if (!m.child_messages) {
							m.child_messages = [];
						}
						m.child_messages.push(message);
						message.parent_message = message.content.root[0];
					}
				}
			}
		}

		for (let message of messages) {
			message.votes = [];
			message.parent_message = undefined;
			message.child_messages = undefined;
		}

		for (let message of messages) {
			try {
				message.content = JSON.parse(message.content);
			} catch {
			}
			if (!messages_by_id[message.id]) {
				messages_by_id[message.id] = message;
				link_message(message);
			} else if (messages_by_id[message.id].placeholder) {
				let placeholder = messages_by_id[message.id];
				messages_by_id[message.id] = message;
				message.parent_message = placeholder.parent_message;
				message.child_messages = placeholder.child_messages;
				message.votes = placeholder.votes;
				if (placeholder.parent_message && messages_by_id[placeholder.parent_message]) {
					let children = messages_by_id[placeholder.parent_message].child_messages;
					children.splice(children.indexOf(placeholder), 1);
					children.push(message);
				}
				link_message(message);
			}
		}

		return messages_by_id;
	}

	update_latest_subtree_timestamp(messages) {
		let latest = 0;
		for (let message of messages || []) {
			if (message.latest_subtree_timestamp === undefined) {
				message.latest_subtree_timestamp = Math.max(message.timestamp ?? 0, this.update_latest_subtree_timestamp(message.child_messages));
			}
			latest = Math.max(latest, message.latest_subtree_timestamp);
		}
		return latest;
	}

	finalize_messages(messages_by_id) {
		function recursive_sort(messages, top) {
			if (messages) {
				if (top) {
					messages.sort((a, b) => b.latest_subtree_timestamp - a.latest_subtree_timestamp);
				} else {
					messages.sort((a, b) => a.timestamp - b.timestamp);
				}
				for (let message of messages) {
					recursive_sort(message.child_messages, false);
				}
				return messages.map(x => Object.assign({}, x));
			} else {
				return {};
			}
		}

		let roots = Object.values(messages_by_id).filter(x => !x.parent_message);
		this.update_latest_subtree_timestamp(roots);
		return recursive_sort(roots, true);
	}

	group_following(messages) {
		let result = [];
		let group = [];
		for (let message of messages) {
			if (message?.content?.type === 'contact') {
				group.push(message);
			} else {
				if (group.length > 0) {
					result.push({
						type: 'contact_group',
						messages: group,
					});
					group = [];
				}
				result.push(message);
			}
		}
		return result;
	}

	load_and_render(messages) {
		let messages_by_id = this.process_messages(messages);
		let final_messages = this.group_following(this.finalize_messages(messages_by_id));
		return html`
			<div style="display: flex; flex-direction: column">
				${final_messages.map(x => html`<tf-message .message=${x} whoami=${this.whoami} .users=${this.users} .drafts=${this.drafts} .expanded=${this.expanded} collapsed=true></tf-message>`)}
			</div>
		`;
	}

	render() {
		return this.load_and_render(this.messages || []);
	}
}

customElements.define('tf-news', TfNewsElement);