import type { EmbedField } from "./embed"
import type { FilledLinkField } from "./link"
import type { FieldState } from "./types"

/**
 * Types enum for RichTextNodes
 *
 * @see More details: {@link https://prismic.io/docs/rich-text-title}
 */
export const RichTextNodeType = {
	heading1: "heading1",
	heading2: "heading2",
	heading3: "heading3",
	heading4: "heading4",
	heading5: "heading5",
	heading6: "heading6",
	paragraph: "paragraph",
	preformatted: "preformatted",
	strong: "strong",
	em: "em",
	listItem: "list-item",
	oListItem: "o-list-item",
	list: "group-list-item",
	oList: "group-o-list-item",
	image: "image",
	embed: "embed",
	hyperlink: "hyperlink",
	label: "label",
	span: "span",
} as const

/**
 * Types for RichTextNodes
 *
 * @see More details: {@link https://prismic.io/docs/rich-text-title}
 */
export type RichTextNodeTypes = (typeof RichTextNodeType)[keyof typeof RichTextNodeType]

// Text nodes

/** Base to be extended by other rich text nodes. */
export interface RTTextNodeBase {
	text: string
	spans: RTInlineNode[]
	direction?: "ltr" | "rtl"
}

/** Rich text `heading1` node */
export interface RTHeading1Node extends RTTextNodeBase {
	type: typeof RichTextNodeType.heading1
}

/** Rich text `heading2` node */
export interface RTHeading2Node extends RTTextNodeBase {
	type: typeof RichTextNodeType.heading2
}

/** Rich text `heading3` node */
export interface RTHeading3Node extends RTTextNodeBase {
	type: typeof RichTextNodeType.heading3
}

/** Rich text `heading4` node */
export interface RTHeading4Node extends RTTextNodeBase {
	type: typeof RichTextNodeType.heading4
}

/** Rich text `heading5` node */
export interface RTHeading5Node extends RTTextNodeBase {
	type: typeof RichTextNodeType.heading5
}

/** Rich text `heading6` node */
export interface RTHeading6Node extends RTTextNodeBase {
	type: typeof RichTextNodeType.heading6
}

/** Rich text `paragraph` node */
export interface RTParagraphNode extends RTTextNodeBase {
	type: typeof RichTextNodeType.paragraph
}

/** Rich text `preformatted` node */
export interface RTPreformattedNode extends RTTextNodeBase {
	type: typeof RichTextNodeType.preformatted
}

/** Rich text `list-item` node */
export interface RTListItemNode extends RTTextNodeBase {
	type: typeof RichTextNodeType.listItem
}

/** Rich text `o-list-item` node for ordered lists */
export interface RTOListItemNode extends RTTextNodeBase {
	type: typeof RichTextNodeType.oListItem
}

// Span nodes

/** @internal Span Node base to be extended for other Span nodes */
export interface RTSpanNodeBase {
	start: number
	end: number
}
/** Rich text `strong` node */
export interface RTStrongNode extends RTSpanNodeBase {
	type: typeof RichTextNodeType.strong
}

/** Rich text `embed` node */
export interface RTEmNode extends RTSpanNodeBase {
	type: typeof RichTextNodeType.em
}

/** Rich text `label` node */
export interface RTLabelNode extends RTSpanNodeBase {
	type: typeof RichTextNodeType.label
	data: {
		label: string
	}
}

// Media nodes

/** Rich text `image` nodes. They could link to other documents, external web links and media fields */
export type RTImageNode = {
	type: typeof RichTextNodeType.image
	id: string
	url: string
	alt: string | null
	copyright: string | null
	dimensions: {
		width: number
		height: number
	}
	edit: {
		x: number
		y: number
		zoom: number
		background: string
	}
	linkTo?: FilledLinkField
}

/** Rich text `embed` node */
export type RTEmbedNode = {
	type: typeof RichTextNodeType.embed
	oembed: EmbedField
}

// Link nodes

/**
 * Rich text `a` node
 *
 * @see More details: {@link https://prismic.io/docs/rich-text-title#elements-and-styles}
 */
export interface RTLinkNode extends RTSpanNodeBase {
	type: typeof RichTextNodeType.hyperlink
	data: FilledLinkField
}

// Serialization related nodes

/** Rich text `list` node */
export interface RTListNode {
	type: typeof RichTextNodeType.list
	items: RTListItemNode[]
}

/** Rich text o-lost node */
export interface RTOListNode {
	type: typeof RichTextNodeType.oList
	items: RTOListItemNode[]
}

// This one is confusing but it's actually the inner content of a block
/** Rich text `span` node */
export interface RTSpanNode extends RTTextNodeBase {
	type: typeof RichTextNodeType.span
}

// Helpers

/** Nodes from a rich text field */
export type RTNode =
	| RTHeading1Node
	| RTHeading2Node
	| RTHeading3Node
	| RTHeading4Node
	| RTHeading5Node
	| RTHeading6Node
	| RTParagraphNode
	| RTPreformattedNode
	| RTListItemNode
	| RTOListItemNode
	| RTImageNode
	| RTEmbedNode

/** Rich text nodes with text */
export type RTTextNode =
	| RTHeading1Node
	| RTHeading2Node
	| RTHeading3Node
	| RTHeading4Node
	| RTHeading5Node
	| RTHeading6Node
	| RTParagraphNode
	| RTPreformattedNode
	| RTListItemNode
	| RTOListItemNode

/** Rich text block nodes */
export type RTBlockNode =
	| RTHeading1Node
	| RTHeading2Node
	| RTHeading3Node
	| RTHeading4Node
	| RTHeading5Node
	| RTHeading6Node
	| RTParagraphNode
	| RTPreformattedNode
	| RTListItemNode
	| RTOListItemNode
	| RTListNode
	| RTOListNode
	| RTImageNode
	| RTEmbedNode

/** Inline rich text nodes */
export type RTInlineNode = RTStrongNode | RTEmNode | RTLabelNode | RTLinkNode

/** All rich text nodes */
export type RTAnyNode = RTBlockNode | RTInlineNode | RTSpanNode

/**
 * A rich text field.
 *
 * @see Rich text field documentation: {@link https://prismic.io/docs/rich-text-title}
 */
export type RichTextField<State extends FieldState = FieldState> = State extends "empty"
	? []
	: [RTNode, ...RTNode[]]
