import {
	Content,
	type ContentAttributes,
	Lifecycle,
	Trigger,
	type TriggerAttributes,
} from "../base/index.js";

export interface IntersectAttributes
	extends TriggerAttributes, ContentAttributes {
	/** Number between 0 and 1 representing the visible portion of the `trigger`. */
	threshold?: number;
}

/**
 * Uses the
 * [Intersection Observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API)
 * to add a `data-intersect` attribute to `content` when the `trigger` is intersecting.
 *
 * ### Events
 *
 * `intersect`
 *
 * Fired when the `trigger` enters the viewport.
 *
 * `exit`
 *
 * Fired when the `trigger` exits the viewport.
 *
 * ### Attributes
 *
 * `threshold`
 *
 * Specify a `threshold` between `0` and `1` to determine how much of the
 * `trigger` should be visible for the intersection to occur.
 */
export class Intersect extends Lifecycle(Trigger(Content())) {
	constructor() {
		super();
	}

	override mount() {
		const observer = new IntersectionObserver(
			(entries) => {
				// attribute to add or remove from `content`
				const attr = "data-intersect";

				for (const entry of entries) {
					if (entry.isIntersecting) {
						this.content().setAttribute(attr, "");
					} else {
						this.content().removeAttribute(attr);
					}

					this.dispatchEvent(
						new CustomEvent(entry.isIntersecting ? "intersect" : "exit", {
							detail: { entry },
						}),
					);
				}
			},
			{ threshold: Number(this.getAttribute("threshold") ?? 0) },
		);

		for (const trigger of this.triggers()) observer.observe(trigger);
	}
}
