import {LitElement, html, 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},
			server_follows_me: {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.server_follows_me = undefined;
	}

	async initial_load() {
		this.server_follows_me = undefined;
		let server_id = await tfrpc.rpc.getServerIdentity();
		let followed = 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') = ? ORDER BY sequence DESC LIMIT 1
		`, [server_id, this.whoami]);
		let is_followed = false;
		for (let row of followed) {
			is_followed = row.following != 0;
		}
		this.server_follows_me = is_followed;
	}

	modify(change) {
		tfrpc.rpc.appendMessage(this.whoami,
			Object.assign({
				type: 'contact',
				contact: this.id,
			}, change)).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,
		};
		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.onchange = function(event) {
			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);
			});
		};
		input.click();
	}

	async server_follow_me(follow) {
		try {
			await tfrpc.rpc.setServerFollowingMe(this.whoami, follow);
		} catch (e) {
			console.log(e);
		}
		try {
			await this.initial_load();
		} catch (e) {
			console.log(e);
		}
	}

	render() {
		if (this.id == this.whoami && this.editing && this.server_follows_me === undefined) {
			this.initial_load();
		}
		let self = this;
		let profile = this.users[this.id] || {};
		tfrpc.rpc.query(
			`SELECT SUM(LENGTH(content)) AS size FROM messages WHERE author = ?`,
			[this.id]).then(function(result) {
				self.size = result[0].size;
			});
		let edit;
		let follow;
		let block;
		if (this.id === this.whoami) {
			if (this.editing) {
				let server_follow;
				if (this.server_follows_me === true) {
					server_follow = html`<input type="button" value="Server, Stop Following Me" @click=${() => this.server_follow_me(false)}></input>`;
				} else if (this.server_follows_me === false) {
					server_follow = html`<input type="button" value="Server, Follow Me" @click=${() => this.server_follow_me(true)}></input>`;
				}
				edit = html`
					<input type="button" value="Save Profile" @click=${this.save_edits}></input>
					<input type="button" value="Discard" @click=${this.discard_edits}></input>
					${server_follow}
				`;
			} else {
				edit = html`<input type="button" value="Edit Profile" @click=${this.edit}></input>`;
			}
		}
		if (this.id !== this.whoami &&
			this.users[this.whoami]?.following) {
			follow =
				this.users[this.whoami].following[this.id] ?
				html`<input type="button" value="Unfollow" @click=${this.unfollow}></input>` :
				html`<input type="button" value="Follow" @click=${this.follow}></input>`;
		}
		if (this.id !== this.whoami &&
			this.users[this.whoami]?.blocking) {
			block =
				this.users[this.whoami].blocking[this.id] ?
				html`<input type="button" value="Unblock" @click=${this.unblock}></input>` :
				html`<input type="button" value="Block" @click=${this.block}></input>`;
		}
		let edit_profile = this.editing ? html`
			<div style="flex: 1 0 50%; display: flex; flex-direction: column">
				<div>
					<label for="name">Name:</label>
					<input type="text" id="name" value=${this.editing.name} @input=${event => this.editing = Object.assign({}, this.editing, {name: event.srcElement.value})}></input>
				</div>
				<div><label for="description">Description:</label></div>
				<textarea style="flex: 1 0" id="description" @input=${event => this.editing = Object.assign({}, this.editing, {description: event.srcElement.value})}>${this.editing.description}</textarea>
				<div>
					<label for="public_web_hosting">Public Web Hosting:</label>
					<input type="checkbox" id="public_web_hosting" value=${this.editing.public_web_hosting} @input=${event => this.editing = Object.assign({}, this.editing, {publicWebHosting: event.srcElement.checked})}></input>
				</div>
				<div>
					<input type="button" value="Attach Image" @click=${this.attach_image}></input>
				</div>
			</div>` : null;
		let image = typeof(profile.image) == 'string' ? profile.image : profile.image?.link;
		image = this.editing?.image ?? image;
		let description = this.editing?.description ?? profile.description;
		return html`<div style="border: 2px solid black; background-color: rgba(255, 255, 255, 0.2); padding: 16px">
			<tf-user id=${this.id} .users=${this.users}></tf-user> (${tfutils.human_readable_size(this.size)})
			<div style="display: flex; flex-direction: row; gap: 1em">
				${edit_profile}
				<div style="flex: 1 0 50%">
					<div><img src=${'/' + image + '/view'} style="width: 256px; height: auto"></img></div>
					<div>${unsafeHTML(tfutils.markdown(description))}</div>
				</div>
			</div>
			<div>
				Following ${Object.keys(profile.following || {}).length} identities.
				Followed by ${Object.values(self.users).filter(x => (x.following || {})[self.id]).length} identities.
				Blocking ${Object.keys(profile.blocking || {}).length} identities.
				Blocked by ${Object.values(self.users).filter(x => (x.blocking || {})[self.id]).length} identities.
			</div>
			<div>
				${edit}
				${follow}
				${block}
			</div>
		</div>`;
	}
}

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