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

class TfTabSearchElement extends LitElement {
	static get properties() {
		return {
			drafts: {type: Object},
			whoami: {type: String},
			users: {type: Object},
			following: {type: Array},
			query: {type: String},
			expanded: {type: Object},
			messages: {type: Array},
			count: {type: Number},
			results: {type: Array},
			error: {type: Object},
			recent_reactions: {type: Array},
			hash: {type: String},
		};
	}

	static styles = styles;

	constructor() {
		super();
		let self = this;
		this.whoami = null;
		this.users = {};
		this.following = [];
		this.expanded = {};
		this.drafts = {};
		tfrpc.rpc.localStorageGet('drafts').then(function (d) {
			self.drafts = JSON.parse(d || '{}');
		});
	}

	async search(query) {
		console.log('Searching...', this.whoami, query);
		let search = this.renderRoot.getElementById('search');
		if (search) {
			search.value = query;
			search.focus();
			search.select();
		}
		await tfrpc.rpc.setHash('#q=' + encodeURIComponent(query));
		this.error = undefined;
		this.results = [];
		this.messages = [];
		this.count = undefined;
		try {
			if (query.startsWith('sql:')) {
				this.messages = [];
				this.results = await tfrpc.rpc.query(
					query.substring('sql:'.length),
					[]
				);
			} else {
				let count = tfrpc.rpc.query(
					`
						SELECT COUNT(*) AS count
						FROM messages_fts(?)
						JOIN messages ON messages.rowid = messages_fts.rowid
						JOIN json_each(?) AS following ON messages.author = following.value
					`,
					['"' + query.replace('"', '""') + '"', JSON.stringify(this.following)]
				);
				let results = await tfrpc.rpc.query(
					`
						SELECT messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
						FROM messages_fts(?)
						JOIN messages ON messages.rowid = messages_fts.rowid
						JOIN json_each(?) AS following ON messages.author = following.value
						ORDER BY timestamp DESC limit 100
					`,
					['"' + query.replace('"', '""') + '"', JSON.stringify(this.following)]
				);
				let self = this;
				count.then((x) => (self.count = x[0].count)).catch(() => {});
				search = this.renderRoot.getElementById('search');
				if (search) {
					search.value = query;
					search.focus();
					search.select();
				}
				this.messages = results;
			}
		} catch (e) {
			this.messages = [];
			this.results = [];
			this.error = e;
			console.log(e);
		}
	}

	on_expand(event) {
		if (event.detail.expanded) {
			let expand = {};
			expand[event.detail.id] = true;
			this.expanded = Object.assign({}, this.expanded, expand);
		} else {
			delete this.expanded[event.detail.id];
			this.expanded = Object.assign({}, this.expanded);
		}
	}

	draft(event) {
		let id = event.detail.id || '';
		let previous = this.drafts[id];
		if (event.detail.draft !== undefined) {
			this.drafts[id] = event.detail.draft;
		} else {
			delete this.drafts[id];
		}
		this.drafts = Object.assign({}, this.drafts);
		tfrpc.rpc.localStorageSet('drafts', JSON.stringify(this.drafts));
	}

	render_results() {
		if (this.error) {
			return html`<h2 style="color: red">${this.error.message}</h2>
				<pre style="color: red">${this.error.stack}</pre>`;
		} else if (this.messages?.length) {
			return html` ${this.count !== undefined
					? html`<p>${this.count} result${this.count === 1 ? '' : 's'}.</p>`
					: undefined}
				<tf-news
					id="news"
					whoami=${this.whoami}
					.users=${this.users}
					.messages=${this.messages}
					.following=${this.following}
					.drafts=${this.drafts}
					.expanded=${this.expanded}
					hash=${this.hash}
					.recent_reactions=${this.recent_reactions}
					@tf-expand=${this.on_expand}
					@tf-draft=${this.draft}
				></tf-news>`;
		} else if (this.results?.length) {
			let keys = Object.keys(this.results[0]).sort();
			return html`<table style="width: 100%; max-width: 100%">
				<tr>
					${keys.map((key) => html`<th>${key}</th>`)}
				</tr>
				${this.results.map(
					(row) =>
						html`<tr>
							${keys.map((key) => html`<td>${row[key]}</td>`)}
						</tr>`
				)}
			</table>`;
		} else {
			return html`<div>No results.</div>`;
		}
	}

	async query_results() {
		if (this.query !== this.last_query) {
			this.last_query = this.query;
			this._query = this.search(this.query);
		}
		await this._query;
	}

	render() {
		return html`
			<style>
				${generate_theme()}
			</style>
			<div class="w3-padding">
				${until(
					this.query_results().then(this.render_results.bind(this)),
					html`<p>Searching...<span class="w3-animate-fading">🦀</span></p>`
				)}
			</div>
		`;
	}
}

customElements.define('tf-tab-search', TfTabSearchElement);
