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

class TfProfileElement extends LitElement {
	static get properties() {
		return {
			editing: {type: Object},
			whoami: {type: String},
			id: {type: String},
			users: {type: Object},
			size: {type: Number},
			sequence: {type: Number},
			following: {type: Boolean},
			blocking: {type: Boolean},
			show_followed: {type: Boolean},
		};
	}

	static styles = styles;

	constructor() {
		super();
		let self = this;
		this.editing = null;
		this.whoami = null;
		this.id = null;
		this.users = {};
		this.size = 0;
		this.sequence = 0;
	}

	async load() {
		if (this.whoami !== this._follow_whoami) {
			this._follow_whoami = this.whoami;
			this.following = undefined;
			this.blocking = undefined;

			let result = await tfrpc.rpc.query(
				`
				SELECT json_extract(content, '$.following') AS following
				FROM messages WHERE author = ? AND
				json_extract(content, '$.type') = 'contact' AND
				json_extract(content, '$.contact') = ? AND
				following IS NOT NULL
				ORDER BY sequence DESC LIMIT 1
			`,
				[this.whoami, this.id]
			);
			this.following = result?.[0]?.following ?? false;
			result = await tfrpc.rpc.query(
				`
				SELECT json_extract(content, '$.blocking') AS blocking
				FROM messages WHERE author = ? AND
				json_extract(content, '$.type') = 'contact' AND
				json_extract(content, '$.contact') = ? AND
				blocking IS NOT NULL
				ORDER BY sequence DESC LIMIT 1
			`,
				[this.whoami, this.id]
			);
			this.blocking = result?.[0]?.blocking ?? false;
		}
	}

	modify(change) {
		let self = this;
		tfrpc.rpc
			.appendMessage(
				this.whoami,
				Object.assign(
					{
						type: 'contact',
						contact: this.id,
					},
					change
				)
			)
			.then(function () {
				self._follow_whoami = undefined;
				self.load();
			})
			.catch(function (error) {
				alert(error?.message);
			});
	}

	follow() {
		this.modify({following: true});
	}

	unfollow() {
		this.modify({following: false});
	}

	block() {
		this.modify({blocking: true});
	}

	unblock() {
		this.modify({blocking: false});
	}

	edit() {
		let original = this.users[this.id];
		this.editing = {
			name: original.name,
			description: original.description,
			image: original.image,
			publicWebHosting: original.publicWebHosting,
		};
		console.log(this.editing);
	}

	save_edits() {
		let self = this;
		let message = {
			type: 'about',
			about: this.whoami,
		};
		for (let key of Object.keys(this.editing)) {
			if (this.editing[key] !== this.users[this.id][key]) {
				message[key] = this.editing[key];
			}
		}
		tfrpc.rpc
			.appendMessage(this.whoami, message)
			.then(function () {
				self.editing = null;
			})
			.catch(function (error) {
				alert(error?.message);
			});
	}

	discard_edits() {
		this.editing = null;
	}

	attach_image() {
		let self = this;
		let input = document.createElement('input');
		input.type = 'file';
		input.addEventListener('change', function (event) {
			input.parentNode.removeChild(input);
			let file = event.target.files[0];
			file
				.arrayBuffer()
				.then(function (buffer) {
					let bin = Array.from(new Uint8Array(buffer));
					return tfrpc.rpc.store_blob(bin);
				})
				.then(function (id) {
					self.editing = Object.assign({}, self.editing, {image: id});
					console.log(self.editing);
				})
				.catch(function (e) {
					alert(e.message);
				});
		});
		document.body.appendChild(input);
		input.click();
	}

	copy_id() {
		navigator.clipboard.writeText(this.id);
	}

	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 = '100vw';
		img.style.maxHeight = '100vh';
		img.style.display = 'block';
		img.style.margin = 'auto';
		img.style.objectFit = 'contain';
		img.style.width = '100vw';
		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);
		}
	}

	toggle_account_list(event) {
		let content = event.srcElement.nextElementSibling;
		this.show_followed = !this.show_followed;
	}

	async load_follows() {
		let accounts = await tfrpc.rpc.following([this.id], 1);
		return html`
			<div class="w3-container">
				<button
					class="w3-button w3-block w3-theme-d1 followed_accounts"
					@click=${this.toggle_account_list}
				>
					${this.show_followed ? 'Hide' : 'Show'} Followed Accounts
					(${Object.keys(accounts).length})
				</button>
				<div class=${'w3-card' + (this.show_followed ? '' : ' w3-hide')}>
					<ul class="w3-ul w3-theme-d4 w3-border-theme">
						${Object.keys(accounts).map(
							(x) => html`
								<li class="w3-border-theme">
									<tf-user id=${x} .users=${this.users}></tf-user>
								</li>
							`
						)}
					</ul>
				</div>
			</div>
		`;
	}

	render() {
		this.load();
		let self = this;
		let profile = this.users[this.id] || {};
		tfrpc.rpc
			.query(
				`SELECT SUM(LENGTH(content)) AS size, MAX(sequence) AS sequence FROM messages WHERE author = ?`,
				[this.id]
			)
			.then(function (result) {
				self.size = result[0].size;
				self.sequence = result[0].sequence;
			});
		let edit;
		let follow;
		let block;
		if (this.id === this.whoami) {
			if (this.editing) {
				edit = html`
					<button
						id="save_profile"
						class="w3-button w3-theme-d1"
						@click=${this.save_edits}
					>
						Save Profile
					</button>
					<button class="w3-button w3-theme-d1" @click=${this.discard_edits}>
						Discard
					</button>
				`;
			} else {
				edit = html`<button
					id="edit_profile"
					class="w3-button w3-theme-d1"
					@click=${this.edit}
				>
					Edit Profile
				</button>`;
			}
		}
		if (this.id !== this.whoami && this.following !== undefined) {
			follow = this.following
				? html`<button class="w3-button w3-theme-d1" @click=${this.unfollow}>
						Unfollow
					</button>`
				: html`<button class="w3-button w3-theme-d1" @click=${this.follow}>
						Follow
					</button>`;
		}
		if (this.id !== this.whoami && this.blocking !== undefined) {
			block = this.blocking
				? html`<button class="w3-button w3-theme-d1" @click=${this.unblock}>
						Unblock
					</button>`
				: html`<button class="w3-button w3-theme-d1" @click=${this.block}>
						Block
					</button>`;
		}
		let edit_profile = this.editing
			? html`
			<div style="flex: 1 0 50%; display: flex; flex-direction: column; gap: 8px">
				<div>
					<label for="name">Name:</label>
					<input class="w3-input w3-theme-d1" type="text" id="name" value=${this.editing.name} @input=${(event) => (this.editing = Object.assign({}, this.editing, {name: event.srcElement.value}))} placeholder="Choose a name"></input>
				</div>
				<div><label for="description">Description:</label></div>
				<textarea class="w3-input w3-theme-d1" style="resize: vertical" rows="8" id="description" @input=${(event) => (this.editing = Object.assign({}, this.editing, {description: event.srcElement.value}))} placeholder="Tell people a little bit about yourself here, if you like.">${this.editing.description}</textarea>
				<div>
					<label for="public_web_hosting">Public Web Hosting:</label>
					<input class="w3-check w3-theme-d1" type="checkbox" id="public_web_hosting" ?checked=${this.editing.publicWebHosting} @input=${(event) => (self.editing = Object.assign({}, self.editing, {publicWebHosting: event.srcElement.checked}))}></input>
				</div>
				<div>
					<button class="w3-button w3-theme-d1" @click=${this.attach_image}>Attach Image</button>
				</div>
			</div>`
			: null;
		let image = profile.image;
		if (typeof image == 'string' && !image.startsWith('&')) {
			try {
				image = JSON.parse(image)?.link;
			} catch {}
		}
		image = this.editing?.image ?? image;
		let description = this.editing?.description ?? profile.description;
		return html`<div class="w3-card-4 w3-container w3-theme-d3" style="box-sizing: border-box">
			<header class="w3-container">
				<p><tf-user id=${this.id} .users=${this.users}></tf-user> (${tfutils.human_readable_size(this.size)} in ${this.sequence} messages)</p>
			</header>
			<div class="w3-container" @click=${this.body_click}>
				<div class="w3-margin-bottom" style="display: flex; flex-direction: row">
					<input type="text" class="w3-input w3-border w3-theme-d1" style="display: flex 1 1" readonly value=${this.id}></input>
					<button class="w3-button w3-theme-d1 w3-ripple" style="flex: 0 0 auto" @click=${this.copy_id}>Copy</button>
				</div>
				<div style="display: flex; flex-direction: row; gap: 1em">
					${edit_profile}
					<div style="flex: 1 0 50%; contain: layout; overflow: auto; word-wrap: normal; word-break: normal">
						${
							image
								? html`<div><img src=${'/' + image + '/view'} style="width: 256px; height: auto"></img></div>`
								: html`<div>
										<div class="w3-jumbo">😎</div>
										<div><i>Profile image not set.</i></div>
									</div>`
						}
						<div>${unsafeHTML(tfutils.markdown(description))}</div>
					</div>
				</div>
				<div>
					Following ${profile.following} identities.
					Followed by ${profile.followed} identities.
					Blocking ${profile.blocking} identities.
					Blocked by ${profile.blocked} identities.
				</div>
			</div>
			${until(this.load_follows(), html`<p>Loading accounts followed...</p>`)}
			<footer class="w3-container">
				<p>
					<a class="w3-button w3-theme-d1" href=${'#🔐' + (this.id != this.whoami ? this.id : '')}>
						Open Private Chat
					</a>
					${edit}
					${follow}
					${block}
				</p>
			</footer>
		</div>`;
	}
}

customElements.define('tf-profile', TfProfileElement);
