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

class TfTabNewsElement extends LitElement {
	static get properties() {
		return {
			whoami: {type: String},
			users: {type: Object},
			hash: {type: String},
			following: {type: Array},
			drafts: {type: Object},
			expanded: {type: Object},
			loading: {type: Boolean},
			channels: {type: Array},
			channels_unread: {type: Object},
			channels_latest: {type: Object},
			connections: {type: Array},
			private_messages: {type: Array},
			grouped_private_messages: {type: Object},
			recent_reactions: {type: Array},
			peer_exchange: {type: Boolean},
			is_administrator: {type: Boolean},
			stay_connected: {type: Boolean},
		};
	}

	static styles = styles;

	constructor() {
		super();
		let self = this;
		this.whoami = null;
		this.users = {};
		this.hash = '#';
		this.following = [];
		this.cache = {};
		this.drafts = {};
		this.expanded = {};
		this.channels_unread = {};
		this.channels_latest = {};
		this.channels = [];
		this.connections = [];
		this.recent_reactions = [];
		tfrpc.rpc.localStorageGet('drafts').then(function (d) {
			self.drafts = JSON.parse(d || '{}');
		});
		this.check_peer_exchange();
	}

	connectedCallback() {
		super.connectedCallback();
		document.body.addEventListener('keypress', this.on_keypress.bind(this));
	}

	disconnectedCallback() {
		super.disconnectedCallback();
		document.body.removeEventListener('keypress', this.on_keypress.bind(this));
	}

	async check_peer_exchange() {
		if (await tfrpc.rpc.isAdministrator()) {
			this.peer_exchange = await tfrpc.rpc.globalSettingsGet('peer_exchange');
		} else {
			this.peer_exchange = undefined;
		}
	}

	load_latest() {
		let news = this.shadowRoot?.getElementById('news');
		if (news) {
			news.load_latest();
		}
	}

	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));
	}

	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);
		}
	}

	on_keypress(event) {
		if (event.target === document.body && event.key == '.') {
			this.show_more();
		}
	}

	unread_status(channel) {
		if (channel === undefined) {
			if (
				Object.keys(this.channels_unread).some((x) => this.unread_status(x))
			) {
				return '✉️ ';
			}
		} else if (channel?.startsWith('🔐')) {
			let key = JSON.stringify(channel.substring('🔐'.length).split(','));
			if (this.grouped_private_messages?.[key]) {
				let grouped_latest = Math.max(
					...this.grouped_private_messages?.[key]?.map((x) => x.rowid)
				);
				if (
					this.channels_unread[channel] === undefined ||
					grouped_latest > this.channels_unread[channel]
				) {
					return '✉️ ';
				}
			}
		} else if (
			this.channels_latest[channel] &&
			this.channels_latest[channel] > 0 &&
			(this.channels_unread[channel] === undefined ||
				this.channels_unread[channel] <= this.channels_latest[channel])
		) {
			return '✉️ ';
		}
	}

	show_sidebar() {
		this.renderRoot.getElementById('sidebar').style.display = 'block';
		this.renderRoot.getElementById('sidebar_overlay').style.display = 'block';
	}

	hide_sidebar() {
		this.renderRoot.getElementById('sidebar').style.display = 'none';
		this.renderRoot.getElementById('sidebar_overlay').style.display = 'none';
	}

	async channel_toggle_subscribed() {
		let channel = this.hash.substring(2);
		let subscribed = this.channels.indexOf(channel) != -1;
		subscribed = !subscribed;

		await tfrpc.rpc.appendMessage(this.whoami, {
			type: 'channel',
			channel: channel,
			subscribed: subscribed,
		});
		if (subscribed) {
			this.channels = [].concat([channel], this.channels).sort();
		} else {
			this.channels = this.channels.filter((x) => x != channel);
		}
	}

	channel() {
		return this.hash.startsWith('##') ? this.hash.substring(2) : undefined;
	}

	compare_follows(a, b) {
		return b[1].ts > a[1].ts ? 1 : b[1].ts < a[1].ts ? -1 : 0;
	}

	suggested_follows() {
		/*
		 ** Filter out people who have used future timestamps so that they aren't
		 ** pinned at the top.
		 */
		let self = this;
		let now = new Date().valueOf();
		return Object.entries(this.users)
			.filter((x) => x[1].ts < now)
			.filter((x) => x[1].follow_depth > 1)
			.sort(self.compare_follows)
			.slice(0, 8)
			.map((x) => x[0]);
	}

	async enable_peer_exchange() {
		await tfrpc.rpc.globalSettingsSet('peer_exchange', true);
		await this.check_peer_exchange();
	}

	is_loading() {
		return this.shadowRoot?.getElementById('news')?.loading;
	}

	render_sidebar() {
		return html`
			<div
				class="w3-sidebar w3-bar-block w3-theme-d1 w3-collapse w3-animate-left"
				style="width: 2in; left: 0; z-index: 5; box-sizing: border-box; top: 0"
				id="sidebar"
			>
				<div
					class="w3-right w3-button w3-hide-large"
					@click=${this.hide_sidebar}
				>
					&times;
				</div>
				${this.is_administrator
					? html`
							<button
								class="w3-bar-item w3-button"
								@click=${() =>
									this.dispatchEvent(
										new Event('refresh', {bubbles: true, composed: true})
									)}
							>
								<span style="display: inline-block; width: 1.8em">↻</span>
								Sync now
							</button>
							<button
								class="w3-bar-item w3-button w3-ripple"
								@click=${() =>
									this.dispatchEvent(
										new Event('toggle_stay_connected', {
											bubbles: true,
											composed: true,
										})
									)}
							>
								<span style="display: inline-block; width: 1.8em"
									>${this.stay_connected ? '🔗' : '⛓️‍💥'}</span
								>
								${this.stay_connected ? 'Online mode' : 'Passive mode'}
							</button>
						`
					: undefined}
				${this.hash.startsWith('##') &&
				this.channels.indexOf(this.hash.substring(2)) == -1
					? html`
							<div class="w3-bar-item w3-theme-d2">Viewing</div>
							<a
								href="#"
								class="w3-bar-item w3-button"
								style="font-weight: bold"
								>${this.hash.substring(2)}</a
							>
						`
					: undefined}
				<h4 class="w3-bar-item w3-theme-d2">Channels</h4>
				<a
					href="#"
					class="w3-bar-item w3-button"
					style=${this.hash == '#' ? 'font-weight: bold' : undefined}
					>${this.unread_status('')}general</a
				>
				<a
					href="#@"
					class="w3-bar-item w3-button"
					style=${this.hash == '#@' ? 'font-weight: bold' : undefined}
					>${this.unread_status('@')}@mentions</a
				>
				<a
					href="#👍"
					class="w3-bar-item w3-button"
					style=${this.hash == '#👍' ? 'font-weight: bold' : undefined}
					>${this.unread_status('👍')}👍votes</a
				>
				${Object.keys(this?.grouped_private_messages ?? [])
					?.sort()
					?.map(
						(key) => html`
							<a
								href=${'#🔐' + JSON.parse(key).join(',')}
								class="w3-bar-item w3-button"
								style=${this.hash == '#🔐' + JSON.parse(key).join(',')
									? 'font-weight: bold'
									: undefined}
								>${this.unread_status('🔐' + JSON.parse(key).join(','))}
								${(key != '[]' ? JSON.parse(key) : [this.whoami]).map(
									(id) => html`
										<tf-user
											id=${id}
											nolink="true"
											.users=${this.users}
										></tf-user>
									`
								)}</a
							>
						`
					)}
				${Object.keys(this.drafts)
					.sort()
					.map(
						(x) => html`
							<a
								href=${'#' + encodeURIComponent(x)}
								class="w3-bar-item w3-button"
								style="text-wrap: nowrap; text-overflow: ellipsis"
								>📝 ${this.drafts[x]?.text ?? x}</a
							>
						`
					)}
				${this.channels.map(
					(x) => html`
						<a
							href=${'#' + encodeURIComponent('#' + x)}
							class="w3-bar-item w3-button"
							style=${this.hash == '##' + x ? 'font-weight: bold' : undefined}
							>${this.unread_status(x)}#${x}</a
						>
					`
				)}

				<a class="w3-bar-item w3-theme-d2 w3-button" href="#connections">
					<h4 style="margin: 0">Connections</h4>
				</a>
				${this.connections?.filter((x) => x.id)?.length == 0
					? html`
							<button
								class=${'w3-bar-item w3-button' +
								(this.connections?.some((x) => x.flags.one_shot)
									? ' w3-spin'
									: '')}
								@click=${() =>
									this.dispatchEvent(
										new Event('refresh', {bubbles: true, composed: true})
									)}
							>
								↻ Sync now
							</button>
							<button
								class=${'w3-bar-item w3-button' +
								(this.peer_exchange !== false ? ' w3-hide' : '')}
								@click=${this.enable_peer_exchange}
							>
								Enable peer exchange
							</button>
						`
					: undefined}
				${this.connections
					.filter((x) => x.id)
					.map(
						(x) => html`
							<tf-user
								class="w3-bar-item"
								style=${x.destroy_reason
									? 'border-left: 4px solid red; border-right: 4px solid red'
									: x.connected
										? x.flags?.one_shot
											? 'border-left: 4px solid blue; border-right: 4px solid blue'
											: 'border-left: 4px solid green; border-right: 4px solid green'
										: ''}
								id=${x.id}
								fallback_name=${x.host}
								.users=${this.users}
							></tf-user>
						`
					)}
				<h4 class="w3-bar-item w3-theme-d2">Suggested Follows</h4>
				${this.suggested_follows().map(
					(x) => html`
						<tf-user
							class="w3-bar-item"
							style="max-width: 100%"
							id=${x}
							.users=${this.users}
						></tf-user>
					`
				)}
			</div>
			<div
				class="w3-overlay"
				id="sidebar_overlay"
				@click=${this.hide_sidebar}
			></div>
		`;
	}

	render() {
		let profile =
			this.hash.startsWith('#@') && this.hash != '#@'
				? keyed(
						this.hash.substring(1),
						html`<tf-profile
							class="tf-profile"
							id=${this.hash.substring(1)}
							whoami=${this.whoami}
							.users=${this.users}
						></tf-profile>`
					)
				: undefined;
		let edit_profile;
		if (
			!this.loading &&
			this.users[this.whoami]?.name === undefined &&
			this.hash.substring(1) != this.whoami
		) {
			edit_profile = html` <div
				class="w3-panel w3-padding w3-round w3-card-4 w3-theme-l3"
			>
				ℹ️ Follow your identity link ☝️ above to edit your profile and set your
				name.
			</div>`;
		}
		return cache(html`
			${this.render_sidebar()}
			<div
				style="margin-left: 2in; padding: 0px; top: 0; height: 100vh; max-height: 100%; overflow: auto; contain: layout"
				id="main"
				class="w3-main"
			>
				<div style="padding: 8px">
					<p>
						${this.hash.startsWith('##')
							? html`
									<button
										class="w3-button w3-theme-d1"
										@click=${this.channel_toggle_subscribed}
									>
										${this.channels.indexOf(this.hash.substring(2)) != -1
											? 'Unsubscribe from #'
											: 'Subscribe to #'}${this.hash.substring(2)}
									</button>
								`
							: undefined}
					</p>
					<div>
						<div
							id="show_sidebar"
							class="w3-button w3-hide-large"
							@click=${this.show_sidebar}
						>
							${this.unread_status()}&#9776;
						</div>
						Welcome, <tf-user id=${this.whoami} .users=${this.users}></tf-user>!
						${edit_profile}
					</div>
					<div>
						<tf-compose
							id="tf-compose"
							whoami=${this.whoami}
							.users=${this.users}
							.drafts=${this.drafts}
							@tf-draft=${this.draft}
							.channel=${this.channel()}
							.recipients=${this.hash.startsWith('#🔐')
								? this.hash.substring('#🔐'.length).split(',')
								: undefined}
						></tf-compose>
					</div>
					${profile}
					<tf-tab-news-feed
						id="news"
						whoami=${this.whoami}
						.users=${this.users}
						.following=${this.following}
						hash=${this.hash}
						.drafts=${this.drafts}
						.expanded=${this.expanded}
						@tf-draft=${this.draft}
						@tf-expand=${this.on_expand}
						.channels_unread=${this.channels_unread}
						.channels_latest=${this.channels_latest}
						.private_messages=${this.private_messages}
						.grouped_private_messages=${this.grouped_private_messages}
						.recent_reactions=${this.recent_reactions}
					></tf-tab-news-feed>
				</div>
			</div>
		`);
	}
}

customElements.define('tf-tab-news', TfTabNewsElement);
