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

class TfMessageElement extends LitElement {
	static get properties() {
		return {
			whoami: {type: String},
			message: {type: Object},
			users: {type: Object},
			reply: {type: Boolean},
			raw: {type: Boolean},
			collapsed: {type: Boolean},
		}
	}

	static styles = styles;

	constructor() {
		super();
		let self = this;
		this.whoami = null;
		this.message = {};
		this.users = {};
		this.reply = false;
		this.raw = false;
		this.collapsed = false;
	}

	show_reply() {
		this.reply = true;
	}

	render_votes() {
		function normalize_expression(expression) {
			if (expression === 'Like' || !expression) {
				return '👍';
			} else if (expression === 'Unlike') {
				return '👎';
			} else if (expression === 'heart') {
				return '❤️';
			} else {
				return expression;
			}
		}
		return html`<div>${(this.message.votes || []).map(
			vote => html`
				<span title="${this.users[vote.author]?.name ?? vote.author} ${new Date(vote.timestamp)}">
					${normalize_expression(vote.content.vote.expression)}
				</span>
			`)}</div>`;
	}

	render_raw() {
		let raw = {
			id: this.message?.id,
			previous: this.message?.previous,
			author: this.message?.author,
			sequence: this.message?.sequence,
			timestamp: this.message?.timestamp,
			hash: this.message?.hash,
			content: this.message?.content,
			signature: this.message?.signature,
		}
		return html`<div style="white-space: pre-wrap">${JSON.stringify(raw, null, 2)}</div>`
	}

	vote(emoji) {
		let reaction = emoji.emoji;
		let message = this.message.id;
		if (confirm('Are you sure you want to react with ' + reaction + ' to ' + message + '?')) {
			tfrpc.rpc.appendMessage(
				this.whoami,
				{
					type: 'vote',
					vote: {
						link: message,
						value: 1,
						expression: reaction,
					},
				}).catch(function(error) {
					alert(error?.message);
				});
		}
	}

	react(event) {
		emojis.picker(x => this.vote(x));
	}

	show_image(link) {
		let div = document.createElement('div');
		div.style.left = 0;
		div.style.top = 0;
		div.style.width = '100%';
		div.style.height = '100%';
		div.style.position = 'fixed';
		div.style.background = '#000';
		div.style.zIndex = 100;
		div.style.display = 'grid';
		let img = document.createElement('img');
		img.src = link;
		img.style.maxWidth = '100%';
		img.style.maxHeight = '100%';
		img.style.display = 'block';
		img.style.margin = 'auto';
		img.style.objectFit = 'contain';
		img.style.width = '100%';
		div.appendChild(img);
		function image_close(event) {
			document.body.removeChild(div);
			window.removeEventListener('keydown', image_close);
		}
		div.onclick = image_close;
		window.addEventListener('keydown', image_close);
		document.body.appendChild(div);
	}

	body_click(event) {
		if (event.srcElement.tagName == 'IMG') {
			this.show_image(event.srcElement.src);
		}
	}

	render_mention(mention) {
		if (!mention?.link || typeof(mention.link) != 'string') {
			return html` <pre>${JSON.stringify(mention)}</pre>`;
		} else if (mention?.link?.startsWith('&') &&
			mention?.type?.startsWith('image/')) {
			return html`
				<img src=${'/' + mention.link + '/view'} style="max-width: 128px; max-height: 128px" title=${mention.name} @click=${() => this.show_image('/' + mention.link + '/view')}>
			`;
		} else if (mention.link?.startsWith('&') &&
			mention.name?.startsWith('audio:')) {
			return html`
				<audio controls style="height: 32px">
					<source src=${'/' + mention.link + '/view'}></source>
				</audio>
			`;
		} else if (mention.link?.startsWith('&') &&
			mention?.type === 'application/tildefriends') {
			return html` <a href=${`/${mention.link}/`}>😎 ${mention.name}</a>`;
		} else if (mention.link?.startsWith('%') || mention.link?.startsWith('@')) {
			return html` <a href=${'#' + encodeURIComponent(mention.link)}>${mention.name}</a>`;
		} else if (mention.link?.startsWith('#')) {
			return html` <a href=${'#q=' + encodeURIComponent(mention.link)}>${mention.link}</a>`;
		} else if (Object.keys(mention).length == 2 && mention.link && mention.name) {
			return html` <a href=${`/${mention.link}/view`}>${mention.name}</a>`;
		} else {
			return html` <pre style="white-space: pre-wrap">${JSON.stringify(mention, null, 2)}</pre>`;
		}
	}

	render_mentions() {
		let mentions = this.message?.content?.mentions || [];
		mentions = mentions.filter(x => x.name?.startsWith('audio:') || this.message?.content?.text?.indexOf(x.link) === -1);
		if (mentions.length) {
			let self = this;
			return html`
				<fieldset style="background-color: rgba(0, 0, 0, 0.1); padding: 0.5em; border: 1px solid black">
					<legend>Mentions</legend>
					${mentions.map(x => self.render_mention(x))}
				</fieldset>
			`;
		}
	}

	render_children() {
		let self = this;
		if (this.collapsed && this.message.child_messages?.length) {
			return html`<input type="button" value=${this.message.child_messages?.length + ' More'} @click=${() => self.collapsed = false}></input>`;
		} else {
			return html`${(this.message.child_messages || []).map(x => html`<tf-message .message=${x} whoami=${this.whoami} .users=${this.users}></tf-message>`)}`;
		}
	}

	render() {
		let content = this.message?.content;
		let self = this;
		let raw_button = this.raw ?
				html`<input type="button" value="Message" @click=${() => self.raw = false}></input>` :
				html`<input type="button" value="Raw" @click=${() => self.raw = true}></input>`;
		function small_frame(inner) {
			return html`
				<div style="border: 1px solid black; background-color: rgba(255, 255, 255, 0.1); margin-top: 8px; padding: 16px; display: inline-block">
					<tf-user id=${self.message.author} .users=${self.users}></tf-user>
					<span style="padding-right: 8px"><a tfarget="_top" href=${'#' + self.message.id}>%</a> ${new Date(self.message.timestamp).toLocaleString()}</span>
					${raw_button}
					${self.raw ? self.render_raw() : inner}
					${self.render_votes()}
				</div>
			`
		}
		if (this.message.placeholder) {
			return html`
				<div style="border: 1px solid black; background-color: rgba(255, 255, 255, 0.1); margin-top: 8px; padding: 16px; overflow-wrap: anywhere">
					<a target="_top" href=${'#' + this.message.id}>${this.message.id}</a> (placeholder)
					<div>${this.render_votes()}</div>
					${(this.message.child_messages || []).map(x => html`
						<tf-message .message=${x} whoami=${this.whoami} .users=${this.users} collapsed=true></tf-message>
					`)}
				</div>`;
		} else if (typeof(content?.type === 'string')) {
			if (content.type == 'about') {
				return small_frame(html`
					<div style="font-weight: bold">Updated profile:</div>
					<pre style="white-space: pre-wrap; overflow-wrap: anywhere">${JSON.stringify(content, null, 2)}</pre>
				`);
			} else if (content.type == 'contact') {
				return small_frame(html`
					<div>
						is
						${
							content.blocking === true ? 'blocking' :
							content.blocking === false ? 'no longer blocking' :
							content.following === true ? 'following' :
							content.following === false ? 'no longer following' :
							'?'
						}
						<tf-user id=${this.message.content.contact} .users=${this.users}></tf-user>
					</div>
				`);
			} else if (content.type == 'post') {
				let reply = this.reply ? html`
					<tf-compose
						?enabled=${this.reply}
						whoami=${this.whoami}
						.users=${this.users}
						root=${this.message.content.root || this.message.id}
						branch=${this.message.id}
						@tf-discard=${() => this.reply = false}></tf-compose>
				` : html`
					<input type="button" value="Reply" @click=${this.show_reply}></input>
				`;
				let self = this;
				let body = this.raw ?
					this.render_raw() :
					unsafeHTML(tfutils.markdown(content.text));
				return html`
					<style>
						code {
							white-space: pre-wrap;
							overflow-wrap: break-word;
						}
						div {
							overflow-wrap: anywhere;
						}
						img {
							max-width: 100%;
							height: auto;
							display: block;
						}
					</style>
					<div style="border: 1px solid black; background-color: rgba(255, 255, 255, 0.1); margin-top: 8px; padding: 16px">
						<div style="display: flex; flex-direction: row">
							<tf-user id=${this.message.author} .users=${this.users}></tf-user>
							<span style="flex: 1"></span>
							<span style="padding-right: 8px"><a target="_top" href=${'#' + self.message.id}>%</a> ${new Date(this.message.timestamp).toLocaleString()}</span>
							<span>${raw_button}</span>
						</div>
						<div @click=${this.body_click}>${body}</div>
						${this.render_mentions()}
						${this.render_votes()}
						<div>
							${reply}
							<input type="button" value="React" @click=${this.react}></input>
						</div>
						${this.render_children()}
					</div>
				`;
			} else if (content.type === 'pub') {
				return small_frame(html`
				<span>
					<div>
						🍻 <tf-user .users=${this.users} id=${content.address.key}></tf-user>
					</div>
					<pre>${content.address.host}:${content.address.port}</pre>
				</span>`);
			} else if (typeof(this.message.content) == 'string') {
				return small_frame(html`<span>🔒</span>`);
			} else {
				return small_frame(html`<div><b>type</b>: ${content.type}</div>`);
			}
		} else {
			return small_frame(this.render_raw());
		}
	}
}

customElements.define('tf-message', TfMessageElement);