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},
			drafts: {type: Object},
			format: {type: String},
			blog_data: {type: String},
			expanded: {type: Object},
		};
	}
	static styles = styles;
	constructor() {
		super();
		let self = this;
		this.whoami = null;
		this.message = {};
		this.users = {};
		this.drafts = {};
		this.format = 'message';
		this.expanded = {};
	}
	show_reply() {
		let event = new CustomEvent('tf-draft', {bubbles: true, composed: true, detail: {id: this.message?.id, draft: {
			encrypt_to: this.message?.decrypted?.recps,
		}}});
		this.dispatchEvent(event);
	}
	discard_reply() {
		this.dispatchEvent(new CustomEvent('tf-draft', {bubbles: true, composed: true, detail: {id: this.id, draft: undefined}}));
	}
	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`
${(this.message.votes || []).map(
			vote => html`
				
					${normalize_expression(vote.content.vote.expression)}
				 
			`)}
`;
	}
	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`${JSON.stringify(raw, null, 2)}
`;
	}
	vote(emoji) {
		let reaction = 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);
		} else if (event.srcElement.tagName == 'DIV' && event.srcElement.classList.contains('img_caption')) {
			let next = event.srcElement.nextSibling;
			if (next.style.display == 'block') {
				next.style.display = 'none';
			} else {
				next.style.display = 'block';
			}
		}
	}
	render_mention(mention) {
		if (!mention?.link || typeof(mention.link) != 'string') {
			return html` ${JSON.stringify(mention)} `;
		} else if (mention?.link?.startsWith('&') &&
			mention?.type?.startsWith('image/')) {
			return html`
				  this.show_image('/' + mention.link + '/view')}>
			`;
		} else if (mention.link?.startsWith('&') &&
			mention.name?.startsWith('audio:')) {
			return html`
				
					 
				 
			`;
		} else if (mention.link?.startsWith('&') &&
			mention.name?.startsWith('video:')) {
			return html`
				
					 
				 
			`;
		} else if (mention.link?.startsWith('&') &&
			mention?.type === 'application/tildefriends') {
			return html` 😎 ${mention.name} `;
		} else if (mention.link?.startsWith('%') || mention.link?.startsWith('@')) {
			return html` ${mention.name} `;
		} else if (mention.link?.startsWith('#')) {
			return html` ${mention.link} `;
		} else if (Object.keys(mention).length == 2 && mention.link && mention.name) {
			return html` ${mention.name} `;
		} else {
			return html` ${JSON.stringify(mention, null, 2)} `;
		}
	}
	render_mentions() {
		let mentions = this.message?.content?.mentions || [];
		mentions = mentions.filter(x => this.message?.content?.text?.indexOf(x.link) === -1);
		if (mentions.length) {
			let self = this;
			return html`
				
					Mentions 
					${mentions.map(x => self.render_mention(x))}
				 
			`;
		}
	}
	total_child_messages(message) {
		if (!message.child_messages) {
			return 0;
		}
		let total = message.child_messages.length;
		for (let m of message.child_messages)
		{
			total += this.total_child_messages(m);
		}
		return total;
	}
	set_expanded(expanded, tag) {
		this.dispatchEvent(new CustomEvent('tf-expand', {bubbles: true, composed: true, detail: {id: (this.message.id || '') + (tag || ''), expanded: expanded}}));
	}
	toggle_expanded(tag) {
		this.set_expanded(!this.expanded[(this.message.id || '') + (tag || '')], tag);
	}
	render_children() {
		let self = this;
		if (this.message.child_messages?.length) {
			if (!this.expanded[this.message.id]) {
				return html`  self.set_expanded(true)}>`;
			} else {
				return html`  self.set_expanded(false)}>${(this.message.child_messages || []).map(x => html` `)}`;
			}
		}
	}
	render_channels() {
		let content = this.message?.content;
		if (this?.messsage?.decrypted?.type == 'post') {
			content = this.message.decrypted;
		}
		let channels = [];
		if (typeof content.channel === 'string') {
			channels.push(`#${content.channel}`);
		}
		if (Array.isArray(content.mentions)) {
			for (let mention of content.mentions) {
				if (typeof mention?.link === 'string' &&
					mention.link.startsWith('#')) {
					channels.push(mention.link);
				}
			}
		}
		return channels.map(x => html` `);
	}
	render() {
		let content = this.message?.content;
		if (this.message?.decrypted?.type == 'post') {
			content = this.message.decrypted;
		}
		let self = this;
		let raw_button;
		switch (this.format) {
			case 'raw':
				if (content?.type == 'post' || content?.type == 'blog') {
					raw_button = html`  self.format = 'md'}>`;
				} else {
					raw_button = html`  self.format = 'message'}>`; 
				}
				break;
			case 'md':
				raw_button = html`  self.format = 'message'}>`;
				break;
			default:
				raw_button = html`  self.format = 'raw'}>`;
				break;
		}
		function small_frame(inner) {
			let body;
			return html`
				
					 
					%  ${new Date(self.message.timestamp).toLocaleString()}
					${raw_button}
					${self.format == 'raw' ? self.render_raw() : inner}
					${self.render_votes()}
				
 
			`;
		}
		if (this.message?.type === 'contact_group') {
			return html`
				
					${this.message.messages.map(x => 
						html` `
					)}
				
`;
		} else if (this.message.placeholder) {
			return html`
				
					${this.message.id}  (placeholder)
					
${this.render_votes()}
					${(this.message.child_messages || []).map(x => html`
						
					`)}
				
 `;
		} else if (typeof(content?.type === 'string')) {
			if (content.type == 'about') {
				let name;
				let image;
				let description;
				if (content.name !== undefined) {
					name = html`Name:  ${content.name}
`;
				}
				if (content.image !== undefined) {
					image = html`
						
					`;
				}
				if (content.description !== undefined) {
					description = html`
						
							${unsafeHTML(tfutils.markdown(content.description))}
						 
					`;
				}
				let update = content.about == this.message.author ?
					html`Updated profile.
` :
					html`Updated profile for  .
`;
				return small_frame(html`
					${update}
					${name}
					${image}
					${description}
				`);
			} else if (content.type == 'contact') {
				return html`
					
						 
						is
						${
							content.blocking === true ? 'blocking' :
							content.blocking === false ? 'no longer blocking' :
							content.following === true ? 'following' :
							content.following === false ? 'no longer following' :
							'?'
						}
						 
					
				`;
			} else if (content.type == 'post') {
				let reply = (this.drafts[this.message?.id] !== undefined) ? html`
					 
				` : html`
					 
				`;
				let self = this;
				let body;
				switch (this.format) {
					case 'raw':
						body = this.render_raw();
						break;
					case 'md':
						body = html`${content.text}`;
						break;
					case 'message':
						body = unsafeHTML(tfutils.markdown(content.text));
						break;
				}
				let content_warning = html`
					 this.toggle_expanded(':cw')}>${content.contentWarning}
					`;
				let content_html =
					html`
						${this.render_channels()}
						${body}
						${this.render_mentions()}
					`;
				let payload =
					content.contentWarning ?
						self.expanded[(this.message.id || '') + ':cw'] ?
							html`
								${content_warning}
								${content_html}
							` :
							content_warning :
						content_html;
				let is_encrypted = this.message?.decrypted ? html`🔓 ` : undefined;
				let style_background = this.message?.decrypted ? 'rgba(255, 0, 0, 0.2)' : 'rgba(255, 255, 255, 0.1)';
				return html`
					
					
						
							
							${is_encrypted}
							
 
							%  ${new Date(this.message.timestamp).toLocaleString()} 
							${raw_button} 
						 
						${payload}
						${this.render_votes()}
						
							${reply}
							 
						
						${this.render_children()}
					
 
				`;
			} else if (content.type === 'issue') {
				let is_encrypted = this.message?.decrypted ? html`🔓 ` : undefined;
				let style_background = this.message?.decrypted ? 'rgba(255, 0, 0, 0.2)' : 'rgba(255, 255, 255, 0.1)';
				return html`
					
					
						
							
							${is_encrypted}
							
 
							%  ${new Date(this.message.timestamp).toLocaleString()} 
							${raw_button} 
						 
						${content.text}
						${this.render_votes()}
						
							 
						
						${this.render_children()}
					
 
				`;
			} else if (content.type === 'blog') {
				let self = this;
				tfrpc.rpc.get_blob(content.blog).then(function(data) {
					self.blog_data = data;
				});
				let payload =
						this.expanded[(this.message.id || '') + ':blog'] ?
						html`${this.blog_data ? unsafeHTML(tfutils.markdown(this.blog_data)) : 'Loading...'}
` :
						undefined;
				let body;
				switch (this.format) {
					case 'raw':
						body = this.render_raw();
						break;
					case 'md':
						body = content.summary;
						break;
					case 'message':
						body = html`
							 self.toggle_expanded(':blog')}>
								
${content.title} 
								
									 
									${content.summary} 
								 
							 
							${payload}
						`;
						break;
				}
				return html`
					
					
						
							 
							 
							%  ${new Date(this.message.timestamp).toLocaleString()} 
							${raw_button} 
						 
						${body}
						${this.render_mentions()}
						${this.render_votes()}
					
 
				`;
			} else if (content.type === 'pub') {
				return small_frame(html`
				
				
					
						🍻  
					
					${content.address.host}:${content.address.port} 
				 `);
			} else if (content.type === 'channel') {
				return small_frame(html`
					
				`);
			} else if (typeof(this.message.content) == 'string') {
				if (this.message?.decrypted) {
					return small_frame(html`🔓 ${JSON.stringify(this.decrypted, null, 2)} `);
				} else {
					return small_frame(html`🔒 `);
				}
			} else {
				return small_frame(html`type : ${content.type}
`);
			}
		} else {
			return small_frame(this.render_raw());
		}
	}
}
customElements.define('tf-message', TfMessageElement);