import { mapMessage } from "../../../context/revoltjs/util";

import { SMOOTH_SCROLL_ON_RECEIVE } from "../Singleton";
import { RendererRoutines } from "../types";

export const SimpleRenderer: RendererRoutines = {
	init: async (renderer, id, smooth) => {
		if (renderer.client!.websocket.connected) {
			renderer
				.client!.channels.fetchMessagesWithUsers(id, {}, true)
				.then(({ messages: data }) => {
					data.reverse();
					let messages = data.map((x) => mapMessage(x));
					renderer.setState(
						id,
						{
							type: "RENDER",
							messages,
							atTop: data.length < 50,
							atBottom: true,
						},
						{ type: "ScrollToBottom", smooth },
					);
				});
		} else {
			renderer.setState(id, { type: "WAITING_FOR_NETWORK" });
		}
	},
	receive: async (renderer, message) => {
		if (message.channel !== renderer.channel) return;
		if (renderer.state.type !== "RENDER") return;
		if (renderer.state.messages.find((x) => x._id === message._id)) return;
		if (!renderer.state.atBottom) return;

		let messages = [...renderer.state.messages, mapMessage(message)];
		let atTop = renderer.state.atTop;
		if (messages.length > 150) {
			messages = messages.slice(messages.length - 150);
			atTop = false;
		}

		renderer.setState(
			message.channel,
			{
				...renderer.state,
				messages,
				atTop,
			},
			{ type: "StayAtBottom", smooth: SMOOTH_SCROLL_ON_RECEIVE },
		);
	},
	edit: async (renderer, id, patch) => {
		const channel = renderer.channel;
		if (!channel) return;
		if (renderer.state.type !== "RENDER") return;

		let messages = [...renderer.state.messages];
		let index = messages.findIndex((x) => x._id === id);

		if (index > -1) {
			let message = { ...messages[index], ...mapMessage(patch) };
			messages.splice(index, 1, message);

			renderer.setState(
				channel,
				{
					...renderer.state,
					messages,
				},
				{ type: "StayAtBottom" },
			);
		}
	},
	delete: async (renderer, id) => {
		const channel = renderer.channel;
		if (!channel) return;
		if (renderer.state.type !== "RENDER") return;

		let messages = [...renderer.state.messages];
		let index = messages.findIndex((x) => x._id === id);

		if (index > -1) {
			messages.splice(index, 1);

			renderer.setState(
				channel,
				{
					...renderer.state,
					messages,
				},
				{ type: "StayAtBottom" },
			);
		}
	},
	loadTop: async (renderer, generateScroll) => {
		const channel = renderer.channel;
		if (!channel) return;

		const state = renderer.state;
		if (state.type !== "RENDER") return;
		if (state.atTop) return;

		const { messages: data } =
			await renderer.client!.channels.fetchMessagesWithUsers(
				channel,
				{
					before: state.messages[0]._id,
				},
				true,
			);

		if (data.length === 0) {
			return renderer.setState(channel, {
				...state,
				atTop: true,
			});
		}

		data.reverse();
		let messages = [...data.map((x) => mapMessage(x)), ...state.messages];

		let atTop = false;
		if (data.length < 50) {
			atTop = true;
		}

		let atBottom = state.atBottom;
		if (messages.length > 150) {
			messages = messages.slice(0, 150);
			atBottom = false;
		}

		renderer.setState(
			channel,
			{ ...state, atTop, atBottom, messages },
			generateScroll(messages[messages.length - 1]._id),
		);
	},
	loadBottom: async (renderer, generateScroll) => {
		const channel = renderer.channel;
		if (!channel) return;

		const state = renderer.state;
		if (state.type !== "RENDER") return;
		if (state.atBottom) return;

		const { messages: data } =
			await renderer.client!.channels.fetchMessagesWithUsers(
				channel,
				{
					after: state.messages[state.messages.length - 1]._id,
					sort: "Oldest",
				},
				true,
			);

		if (data.length === 0) {
			return renderer.setState(channel, {
				...state,
				atBottom: true,
			});
		}

		let messages = [...state.messages, ...data.map((x) => mapMessage(x))];

		let atBottom = false;
		if (data.length < 50) {
			atBottom = true;
		}

		let atTop = state.atTop;
		if (messages.length > 150) {
			messages = messages.slice(messages.length - 150);
			atTop = false;
		}

		renderer.setState(
			channel,
			{ ...state, atTop, atBottom, messages },
			generateScroll(messages[0]._id),
		);
	},
};