import { PaperSize, PdfPaperOrientation, PdfPaperSize } from "./paper";
import { HtmlAffix, TextAffix } from "./affix";
import {
        CssMediaType,
        FitToPaperModes,
        MarginConfig,
        UseMargins,
        TableOfContentsTypes,
} from "./types";

/**
 * Represents the rendered location of an HTML element within a PDF document.
 *
 * Returned by {@code PdfDocument.getElementLocations()} after rendering HTML with
 * {@link ChromePdfRenderOptions.elementQuerySelectors} configured.
 *
 * Mirrors {@code IronPdf.RenderedElementLocation} on the C# side.
 */
export interface RenderedElementLocation {
	/**
	 * The text content of the matched element.
	 */
	text: string;
	/**
	 * The zero-based page index where the element was rendered.
	 */
	pageIndex: number;
	/**
	 * The bounding rectangle of the annotation marker on the page, in PDF points (1/72 inch).
	 * Coordinate origin is the bottom-left corner of the page. The rectangle corresponds to
	 * the injected anchor marker placed at the start of the matched element.
	 */
	rectangle: { x: number; y: number; width: number; height: number };
	/**
	 * The original index of the element in document order among all matched elements.
	 */
	elementIndex: number;
}
 
/**
 * Specifies the linearization strategy to use when producing a linearized
 * (web-optimized) PDF.
 *
 * Mirrors {@code IronPdf.LinearizationMode} on the C# side.
 */
export enum LinearizationMode {
	/**
	 * Automatically selects the optimal linearization method based on system capabilities.
	 *
	 * Behavior:
	 *   1. First attempts {@link FileBased} linearization.
	 *   2. If disk access is restricted (e.g. limited permissions, sandboxed environment),
	 *      automatically falls back to {@link InMemory}.
	 *
	 * Recommended default for most applications.
	 */
	Automatic = 0,
	/**
	 * Performs linearization entirely in memory without any disk I/O operations.
	 *
	 * Use when:
	 *   - Compliance requirements mandate zero disk I/O (e.g. HIPAA, PCI-DSS)
	 *   - Sandboxed or restricted environments without disk write permissions
	 *   - Cloud-based environments where disk I/O introduces latency
	 */
	InMemory = 1,
	/**
	 * Performs linearization using temporary file operations on disk.
	 * Requires write permissions to the system temporary directory.
	 */
	FileBased = 2,
}

/**
 * Html or Url To PDF output options for {@link PdfGenerator} and {@link PdfDocument} static method.
 * Specify options such as Paper-Size, DPI and other Chromium specific browser setup options.
 */
export interface ChromePdfRenderOptions {
	// applyMarginToHeaderAndFooter ?: boolean | undefined;
	/**
	 * Is create pdf forms from html. Turns all Html forms elements into editable PDF forms.
	 *
	 * @default true
	 */
	createPdfFormsFromHtml ?: boolean | undefined;
	/**
	 * Allows a custom CSS style-sheet to be applied to Html before rendering.
	 *
	 * Maybe a local file path or remote url.
	 *
	 * @default undefined
	 */
        customCssUrl ?: string | undefined;
	/**
	 * Enables JavaScript and Json to be executed  before the page is rendered.
	 *
	 * Ideal for printing from Ajax / Angular Applications. <p>Also see {@link waitFor}
	 *
	 * @default true
	 */
	enableJavaScript ?: boolean | undefined;
	/**
	 * Behavior when fitting HTML content to a physical paper size.
	 * Determines {@link zoom} and  {@link viewPortWidth}.
	 * See {@link FitToPaperModes} for a detailed description of each mode.
	 * {@link FitToPaperModes.Default} disables automatic fitting behavior.
	 *
	 * @default {@link FitToPaperModes.Default}
	 */
	fitToPaperMode?: FitToPaperModes | undefined;
	/**
	 * Outputs a black-and-white PDF
	 *
	 * @default false
	 */
	grayScale ?: boolean | undefined;
	/**
	 * Pdf "paper" margin in millimeters.
	 *
	 * Set to zero for border-less and commercial printing applications.
	 * @default {@link MarginConfig} default 25
	 */
	margin?: MarginConfig | undefined;
	/**
	 * The PDF paper orientation.
	 *
	 * @default {@link PdfPaperOrientation.Portrait}
	 */
	paperOrientation?: PdfPaperOrientation | undefined;
	/**
	 * Set an output paper size for PDF pages.
	 * Use {@link customPaperWidthMm}, {@link customPaperHeightMm} for custom sizes.
	 *
	 * @default {@link PaperSize.A4}
	 */
	paperSize?: PdfPaperSize | undefined;
	/**
	 * Prints background-colors and images from Html.
	 *
	 * @default true
	 */
	printHtmlBackgrounds ?: boolean | undefined;
	/**
	 * Render timeout in seconds
	 * @default 60
	 */
	timeout ?: number | undefined;
	/**
	 * A wrapper object that holds configuration for wait-for mechanism for user to wait for certain events before rendering.
	 *
	 * @default {@link WaitForRenderDelay} with 20 milliseconds
	 */
	waitFor?: WaitFor | undefined;
	/**
	 * PDF Document Name and Title meta-data.  Not required.  Useful for mail-merge and automatic file naming in the IronPdf MVC and Razor extensions.
	 */
	title ?: string | undefined;
	// viewPortHeight ?: number | undefined;
	// viewPortWidth ?: number | undefined;
	// zoom ?: number | undefined;
	inputEncoding ?: string | undefined;
	cssMediaType?: CssMediaType | undefined;
	javascript ?: string | undefined;
	firstPageNumber ?: number | undefined;
	/**
	 * Include a table of contents generated from heading elements.
	 */
	tableOfContents?: TableOfContentsTypes | undefined;
	htmlHeader?: HtmlAffix | undefined;
	htmlFooter?: HtmlAffix | undefined;
	textHeader?: TextAffix | undefined;
	textFooter?: TextAffix | undefined;
	/**
	 *  Use margin values from the main document when rendering headers and footers
	 *  @default {@link UseMargins.LeftAndRight}
	 */
	useMarginsOnHeaderAndFooter?: UseMargins | undefined;
	/**
	 * If true, auto-generate PDF outline (bookmarks) from the HTML heading structure.
	 * Use {@link autoBookmarkMinHeadingLevel} / {@link autoBookmarkMaxHeadingLevel} to control
	 * which heading levels are included (1 = h1, 6 = h6). Use {@link autoBookmarkCssSelectors}
	 * to include additional non-heading elements (e.g. {@code ".chapter-title"}).
	 *
	 * @default false
	 */
	autoBookmarksFromHeadings?: boolean | undefined;
	/**
	 * Minimum heading level (inclusive) to include in auto-generated bookmarks.
	 * Only used when {@link autoBookmarksFromHeadings} is true.
	 *
	 * @default 1
	 */
	autoBookmarkMinHeadingLevel?: number | undefined;
	/**
	 * Maximum heading level (inclusive) to include in auto-generated bookmarks.
	 * Only used when {@link autoBookmarksFromHeadings} is true.
	 *
	 * @default 6
	 */
	autoBookmarkMaxHeadingLevel?: number | undefined;
	/**
	 * Additional CSS selectors whose matching elements will be included as auto-bookmarks
	 * (in addition to the heading range). Only used when {@link autoBookmarksFromHeadings} is true.
	 * Example: {@code [".chapter-title", "[data-bookmark]"]}.
	 */
	autoBookmarkCssSelectors?: string[] | undefined;
	/**
	 * CSS selectors whose matching HTML elements should be tracked during rendering so their
	 * rendered page positions can later be retrieved by the engine.
	 *
	 * <b>Note:</b> retrieval of the per-element locations from the Node client is not yet
	 * supported. Setting this option still enables engine-side tracking (and any downstream
	 * effects such as auto-bookmarks for those selectors).
	 */
	elementQuerySelectors?: string[] | undefined;
}

/**
 *  A managed wrapper of wait-for configurations. see {@link ChromePdfRenderOptions.waitFor}
 */
export type WaitFor =
	| WaitForRenderDelay
	| WaitForPageLoad
	| WaitForJavaScript
	| WaitForNetworkIdleN
	| WaitForNetworkIdle0
	| WaitForNetworkIdle2
	| WaitForHtmlQuerySelector

/**
 * A wait-for type. see {@link ChromePdfRenderOptions.waitFor} also {@link WaitFor}
 */
export enum WaitForType {
	PageLoad = "PageLoad",
	JavaScript = "JavaScript",
	RenderDelay = "RenderDelay",
	NetworkIdle0 = "NetworkIdle0",
	NetworkIdle2 = "NetworkIdle2",
	NetworkIdleN = "NetworkIdleN",
	HtmlElement = "HtmlElement",
}

/**
 * Configurations for wait-for an initial delay before rendering.
 */
export interface WaitForRenderDelay {
	type: WaitForType.RenderDelay;
	/**
	 * Delay time in milliseconds before rendering
	 *
	 * @default 20 milliseconds
	 */
	delay ?: number | undefined;
}

/**
 * Proceeds rendering by waiting until user calls our JS function `window.ironpdf.notifyRender()`
 */
export interface WaitForJavaScript {
	type: WaitForType.JavaScript;
	/**
	 * Maximum wait time in milliseconds until it forces rendering.
	 * @default 10000 milliseconds
	 */
	maxWaitTime ?: number | undefined;
}

/**
 *  Proceeds rendering by waiting until it internally detects a network idle event when there is no network activity
 *  after at least specified {@link networkIdleDuration} as well as at maximum of {@link maxNumAllowedInflight} inflight (outstanding) network requests.
 */
export interface WaitForNetworkIdleN {
	type: WaitForType.NetworkIdleN;
	/**
	 * Duration of time in milliseconds to regard as network idle event
	 */
	networkIdleDuration ?: number | undefined;
	/**
	 * Maximum number of allowed inflight network requests to not invalidate network idle event
	 */
	maxNumAllowedInflight ?: number | undefined;
	/**
	 * Maximum wait time in milliseconds until it forces rendering. Default value is 10000 milliseconds
	 */
	maxWaitTime ?: number | undefined;
}

/**
 * Proceeds rendering by waiting until it internally detects a network idle event when there is no network activity
 * after at least 500ms as well as no inflight (outstanding) network requests.
 */
export interface WaitForNetworkIdle0 {
	type: WaitForType.NetworkIdle0;
	/**
	 * Maximum wait time in milliseconds until it forces rendering.
	 * @default 10000 milliseconds
	 */
	maxWaitTime ?: number | undefined;
}

/**
 * This method proceeds rendering by waiting until it internally detects a network idle event when there is no network activity
 * after at least 500ms as well as at maximum of 2 inflight (outstanding) network request.
 */
export interface WaitForNetworkIdle2 {
	type: WaitForType.NetworkIdle2;
	/**
	 * Maximum wait time in milliseconds until it forces rendering.
	 * @default 10000 milliseconds
	 */
	maxWaitTime ?: number | undefined;
}

/**
 * Basically it waits for nothing, but will render as soon as the page loaded.
 */
export interface WaitForPageLoad {
	type: WaitForType.PageLoad;
}

/**
 * Waiting until it finds the HTML element via the specified query string which is executed by a JavaScript function
 * Read querySelector() documentation: {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector}
 */
export interface WaitForHtmlQuerySelector {
	type: WaitForType.HtmlElement;
	/**
	 * HTML element query string to query for with Javascript's document.querySelector()
	 */
	htmlQueryStr: string,
	/**
	 * Maximum wait time in milliseconds until it forces rendering.
	 * @default 10000 milliseconds
	 */
	maxWaitTime ?: number | undefined;
}

export function defaultChromePdfRenderOptions(): ChromePdfRenderOptions {
        return {
                cssMediaType: CssMediaType.Print,
                enableJavaScript: true,
                firstPageNumber: 1,
                tableOfContents: TableOfContentsTypes.None,
                fitToPaperMode: FitToPaperModes.Default,
		grayScale: false,
		inputEncoding: "utf-8",
		margin: { default: 0.38, top: 0.39, left: 0.39 },
		paperSize: PaperSize.A4,
		paperOrientation: PdfPaperOrientation.Portrait,
		printHtmlBackgrounds: true,
		waitFor: { type: WaitForType.RenderDelay, delay: 20 },
		// viewPortWidth: 1280,
		// viewPortHeight: 1024,
		// zoom: 100,
		createPdfFormsFromHtml: true,
                customCssUrl: "",
                useMarginsOnHeaderAndFooter: UseMargins.All,
        };
}

/**
 *  Provides credentials for IronPdf's embedded Chrome browser to log in to an intranet, extranet or website, impersonating a user.
 *  This allows a unique ability to render web-pages as PDFs even on secure intranets, extranets and websites.
 */
export interface HttpLoginCredentials {
	/**
	 * A Dictionary which allows custom cookies to be posted with every login request, and HTTP request made by
	 * RenderUriToHml methods.
	 */
	custom_cookies?: Map<string, string> | undefined;
	/**
	 * Enables cookies to be stored and sent when using RenderUriToHml methods.
	 */
	enable_cookies ?: boolean | undefined;
	/**
	 * Optional: Password credential for Windows / Linux network security authentication.
	 */
	network_password ?: string | undefined;
	/**
	 * Optional: User-name credential for Windows / Linux network security authentication.
	 */
	network_username ?: string | undefined;
}
