"use client";

import {
	useEffect,
	useRef,
	useImperativeHandle,
	forwardRef,
	RefObject,
} from "react";
import "@xterm/xterm/css/xterm.css";

export type TerminalRef = {
	write: (data: string) => void;
	clear: () => void;
	focus: () => void;
};

export const Terminal = forwardRef<
	TerminalRef,
	{
		onData: (data: String) => void;
	}
>(function Terminal(props, ref) {
	const terminalRef = useRef<HTMLDivElement>(null);
	const xtermRef = useRef<any>(null);

	useImperativeHandle(ref, () => ({
		write: (data: string) => {
			if (xtermRef.current) {
				xtermRef.current.write(data);
			}
		},
		clear: () => {
			if (xtermRef.current) {
				xtermRef.current.clear();
			}
		},
		focus: () => {
			if (xtermRef.current) {
				xtermRef.current.focus();
			}
		},
	}));

	useEffect(() => {
		// Set to false when this component is unmounted.
		//
		// Here's what this flag prevents:
		// - <Terminal> component mounts
		// - `useEffect` runs, `mounted = true`
		// - `init_term()` function begins work
		// - before init_term() finishes, the user navigates away and <Terminal> to unmounts
		// - `useEffect` cleans up, `mounted = false`
		// - `init_term()` ccompletes, and we attempt to set `xtermRef.current`, causing issues
		let mounted = true;

		init_term(terminalRef, props.onData, () => mounted)
			.then((term) => {
				if (!mounted) return;
				xtermRef.current = term;
			})
			.catch((err) => {
				console.error("Failed to initialize terminal:", err);
			});

		return () => {
			mounted = false;
			if (xtermRef.current) {
				xtermRef.current.dispose();
				xtermRef.current = null;
			}
		};
	}, [props.onData]);

	return <div ref={terminalRef} style={{ height: "100%", width: "100%" }} />;
});

async function init_term(
	ref: RefObject<HTMLDivElement>,

	// Called when the terminal receives data
	onData: (data: String) => void,
	isMounted: () => boolean
) {
	if (!ref.current) return;

	const { Terminal } = await import("@xterm/xterm");
	if (!isMounted()) return;

	const term = new Terminal({
		//"fontFamily": "Fantasque",
		rows: 24,
		fontSize: 16,
		tabStopWidth: 8,
		cursorBlink: false,
		cursorStyle: "block",
		cursorInactiveStyle: "none",
		theme: {
			background: "#1D1F21",
			foreground: "#F8F8F8",
			cursor: "#F8F8F2",
			black: "#282828",
			blue: "#0087AF",
			brightBlack: "#555555",
			brightBlue: "#87DFFF",
			brightCyan: "#28D1E7",
			brightGreen: "#A8FF60",
			brightMagenta: "#985EFF",
			brightRed: "#FFAA00",
			brightWhite: "#D0D0D0",
			brightYellow: "#F1FF52",
			cyan: "#87DFEB",
			green: "#B4EC85",
			magenta: "#BD99FF",
			red: "#ff2f00ff",
			white: "#F8F8F8",
			yellow: "#FFFFB6",
		},
	});

	term.open(ref.current);
	term.onData(onData);

	console.log("Terminal ready");
	return term;
}
