/*!
Copyright 2024 apHarmony

This file is part of jsHarmony.

jsHarmony is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

jsHarmony is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this package.  If not, see <http://www.gnu.org/licenses/>.
*/


import { GetServerSidePropsResult } from 'next';
import { Metadata } from 'next';
import { NextRequest } from 'next/server';
import { NextResponse } from 'next/server';
import { PropsWithChildren } from 'react';
import { default as React_2 } from 'react';
import { ReactElement } from 'react';
import { ResolvingMetadata } from 'next';
import { ValidationMap } from 'react';
import { WeakValidationMap } from 'react';

/**
 * JshCms - renders head, editor, script, style, footer tags, and a container for JshCmsContentArea tags
 * @remarks
 *
 * @example
 * ```
 * <JshCms jshCmsPage={jshCmsPage} jshCmsConfig={JshCmsConfig}>
 *   <h1 cms-title="true">{jshCmsPage.title||'Title'}</h1>
 *   <JshCmsContentArea cms-content="body">Page Content</JshCmsContentArea>
 * </JshCms>
 * ```
 * @public
 */
export declare function JshCms(props: JshCmsProps): React_2.JSX.Element;

/**
 * @public
 */
export declare interface JshCmsConfig {
    /** URL to published CMS content files */
    contentUrl?: string;
    /** Path to redirect listing JSON file (relative to contentUrl) */
    redirectListingPath?: string | null;
    /** Default Directory Document (e.g. index.html) */
    defaultDocument?: string;
    /** The CMS Server URLs that will be enabled for Page Editing (set to '*' to enable any remote CMS)
     * - Used by jshCmsPage.editorScriptPath, and the getEditorScriptPath function
     * - NOT used by jsHarmonyCmsEditor.js - the launcher instead uses accessKeys for validating the remote CMS
     */
    cmsServerUrls?: string[];
    /** Cache duration (seconds) */
    cacheDuration?: number;
}

/**
 * JshCmsContentArea - Render content area.
 * @remarks
 * React function component for rendering content area content and associated portals for child component rendering.
 *
 * @example
 * ```
 * <JshCmsContentArea cms-content="body" jshCmsPage={jshCmsPage}>
 *   Optional Default Body Content
 * </JshCmsContentArea>
 * ```
 * @public
 */
export declare function JshCmsContentArea(props: JshCmsContentAreaProps): React_2.JSX.Element;

/**
 * @public
 */
export declare interface JshCmsContentAreaProps {
    jshCmsPage?: JshCmsPage;
    jshCmsContentComponents?: JshCmsContentComponent<any>[];
    ['cms-content']: string;
    [key: string]: any;
}

/**
 * JshCmsContentComponent - Content Component.
 * @public
 */
export declare interface JshCmsContentComponent<P = {}> {
    (props: PropsWithChildren<P>, context?: any): ReactElement<any, any> | null;
    propTypes?: WeakValidationMap<P> | undefined;
    contextTypes?: ValidationMap<any> | undefined;
    defaultProps?: Partial<P> | undefined;
    displayName?: string | undefined;
    jshCmsComponentConfig?: JshCmsContentComponentConfig | undefined;
}

/**
 * JshCmsContentComponent - Content Component.
 * @public
 */
export declare class JshCmsContentComponent<P = {}> implements JshCmsContentComponent<P> {
    static extractChildrenAsReactElements(container: Element): ReactElement[];
}

/**
 * JshCmsContentComponent - Content Component Config.
 * @public
 */
export declare interface JshCmsContentComponentConfig {
    selector: string;
    onBeforeRender?: (componentContainer: Element, contentComponentProps: JshCmsContentComponentProps | null) => void;
    onRender?: (componentContainer: Element, contentComponentProps: JshCmsContentComponentProps | null) => void;
    render?: (componentContainer: Element, contentComponentProps: JshCmsContentComponentProps | null) => JshCmsContentComponentRender | undefined;
}

/**
 * JshCmsContentComponentInstance - Content Component Instance.
 * @public
 */
export declare interface JshCmsContentComponentInstance {
    container: Element;
    element: ReactElement;
    key: string;
}

/**
 * @public
 */
export declare interface JshCmsContentComponentProps {
    data: unknown;
    properties: unknown;
    isInEditor: boolean;
    isInPageEditor: boolean;
    isInComponentEditor: boolean;
    isItemPreview: boolean;
    isGridRowPreview: boolean;
}

/**
 * JshCmsContentComponentInstance - Content Component Render Parameters.
 * @public
 */
export declare interface JshCmsContentComponentRender {
    container?: Element;
    element: ReactElement;
    key?: string;
}

/**
 * @internal
 */
export declare const JshCmsContext: React_2.Context<JshCmsContextData>;

/**
 * @public
 */
export declare interface JshCmsContextData {
    jshCmsConfig: JshCmsConfig | undefined;
    jshCmsPage: JshCmsPage | undefined;
}

/**
 * JshCmsEditor - render editor support script when page is loaded in the CMS editor.
 * @remarks
 * Simple React function component for conditionally including tags in pages. These are trivial and can be replaced with custom code as needed.
 * Note: CMS was designed to support additional head tags. Next.js takes full control of the head, so these must be placed elsewhere.
 *
 * @example
 * ```
 * <JshCmsEditor jshCmsPage={jshCmsPage} />
 * ```
 * @public
 */
export declare function JshCmsEditor(props: JshCmsElementProps): React_2.JSX.Element;

/**
 * @public
 */
export declare interface JshCmsElementProps {
    jshCmsPage?: JshCmsPage;
    [key: string]: any;
}

/**
 * JshCsFooter - render additional footer tags (if any).
 * @remarks
 * Simple React function component for conditionally including tags in pages. These are trivial and can be replaced with custom code as needed.
 *
 * @example
 * ```
 * <JshCmsFooter jshCmsPage={jshCmsPage} />
 * ```
 * @public
 */
export declare function JshCmsFooter(props: JshCmsElementProps): React_2.JSX.Element;

/**
 * JshCmsHead - render additional head tags (if any). Note that this feature in particular is questionable with the Next.js head management, and since raw text must have a container, it is rendered in a div.
 * @remarks
 * Simple React function component for conditionally including tags in pages. These are trivial and can be replaced with custom code as needed.
 * Note: CMS was designed to support additional head tags. Next.js takes full control of the head, so these must be placed elsewhere.
 *
 * @example
 * ```
 * <JshCmsHead jshCmsPage={jshCmsPage} />
 * ```
 * @public
 */
export declare function JshCmsHead(props: JshCmsElementProps): React_2.JSX.Element;

/**
 * @public
 */
export declare interface JshCmsMetadataProps {
    params: {
        [key: string]: string[] | string | undefined;
    };
}

/**
 * @public
 */
export declare interface JshCmsPage {
    content: {
        [areaId: string]: string;
    };
    css: string;
    /** If page was opened from a CMS Editor in config.cmsServerUrls, the HTML script to launch the Editor */
    editorScriptPath: string | null;
    footer: string;
    header: string;
    /** Whether the page was opened from the CMS Editor */
    isInEditor: boolean;
    js: string;
    page_template_id: string;
    properties: {
        [propName: string]: any;
    };
    seo: {
        canonical_url: string;
        keywords: string;
        metadesc: string;
        /** Title for HEAD */
        title: string;
    };
    /** Title for Page Body Content */
    title: string;
    /** Whether the page was Not Found (page data will return empty) */
    notFound: boolean;
}

/**
 * @public
 */
export declare class JshCmsPage implements JshCmsPage {
    /**
     * getEmptyPage - An empty JshCmsPage object, for blank editors or initializing useState
     * @param pageTemplateId - page template id for newly created pages
     * @public
     */
    static getEmptyPage(pageTemplateId: string): JshCmsPage;
    /**
     * getNotFoundPage - An empty JshCmsPage object, with the notFound flag set
     * @param pageTemplateId - page template id for newly created pages
     * @public
     */
    static getNotFoundPage(pageTemplateId: string): JshCmsPage;
    /**
     * getPage - Get CMS Page Data
     * @param pathname - Root-relative Page URL
     * @param params - Page load parameters
     * @param config - Configuration parameters
     * @public
     */
    static getPage(pathname: string[] | string | undefined, params: {
        [key: string]: string[] | string | undefined;
    }, config: JshCmsPageRequest): Promise<JshCmsPage>;
    /**
     * getMetadata - provides a basic version of a Next.js metadata function that provides CMS SEO data.
     *
     * @remarks
     * If you application has additional metadata needs, you may wish to copy this function into your generateMetadata function.
     * {@link https://nextjs.org/docs/app/api-reference/functions/generate-metadata}
     *
     * @param props - params from the incoming request
     * @param parent - metadata from previous functions
     * @param config - CMS configuration parameters
     * @public
     */
    static getMetadata({ params }: JshCmsMetadataProps, // eslint-disable-line @typescript-eslint/no-unused-vars
    parent: ResolvingMetadata, config: JshCmsPageRequest): Promise<Metadata>;
    /**
     * getEditorScriptPath - Generate script for CMS Editor
     * @remarks
     * - The provided url is validated against cmsServerUrls
     * - If the CMS Server is not found in cmsServerUrls, an empty element will be returned
     *
     * @param cmsServerUrl - URL from jshcms_url parameter
     * @param cmsServerUrls - list of allowed CMS editor servers
     * @returns path to the editor script
     *
     * @public
     */
    static getEditorScriptPath(cmsServerUrl: string, cmsServerUrls: string[]): string | null;
    /**
     * getStandalonePage [Main Entry Point] - Get CMS Page Data for Standalone Integration
     * @remarks
     * if page is opened from CMS Editor or Not Found, an empty JshCmsPage Object will be returned
     *
     * @param pathname - Root relative path being requested
     * @param params - Request url parameters
     * @param config - CMS Configuration parameters
     * @returns JshCmsPage Object, with set properties: isInEditor, editorScriptPath, notFound
     * @public
     */
    static getStandalonePage(pathname: string[] | string | undefined, params: {
        [key: string]: string[] | string | undefined;
    }, config: JshCmsPageRequest): Promise<JshCmsPage>;
    /**
     * getPath - Transform a page url into cms content file path
     * @param contentUrl - CMS content export folder
     * @param pathname - Root relative path being requested
     * @returns normalized path
     * @public
     */
    static getPath(contentUrl: string, pathname: string): string;
    /**
     * getPathVariations - creations variations of a cms content path to try, e.g. as provided and with index.html
     * @param pathname - Root relative path being requested
     * @param defaultDocument - default document if not in url, e.g. 'index.html'
     * @returns list of paths to try
     * @public
     */
    static getPathVariations(pathname: string, defaultDocument: string): string[];
    /**
     * resolvePath - Convert URL to CMS Content Paths
     * @param contentUrl - CMS content URL
     * @param pathname - Root relative path being requested
     * @param defaultDocument - default document if not in url, e.g. 'index.html'
     * @returns list of paths to try
     * @public
     */
    static resolvePath(contentUrl: string, pathname: string, defaultDocument: string): string[];
}

/**
 * JshCmsPageComponent - Page Component.
 * @public
 */
export declare function JshCmsPageComponent(props: JshCmsPageComponentProps): React_2.JSX.Element;

/**
 * @public
 */
export declare interface JshCmsPageComponentProps {
    componentId: string;
    [key: string]: any;
}

/**
 * JshCmsPageConfig - render config settings as a script tag
 * @remarks
 * Simple React function component for conditionally including tags in pages. These are trivial and can be replaced with custom code as needed.
 * Note: CMS was designed to support additional head tags. Next.js takes full control of the head, so these must be placed elsewhere.
 *
 * @example
 * ```
 <JshCmsPageConfig cms-template="Two Column Page Template" config={{
 "content_elements": {
 "left": { "title": "Left" },
 "right": { "title": "Right" }
 }
 }} />
 * ```
 * @public
 */
export declare function JshCmsPageConfig(props: JshCmsPageConfigProps): React_2.JSX.Element | undefined;

/**
 * @public
 */
export declare interface JshCmsPageConfigDefinition {
    title?: string;
    /**
     * Each editable content area has one entry in
     * content_elements. If no content areas are defined,
     * a default content area named "body" will be added.
     */
    content_elements?: {
        [content_area_name: string]: {
            title?: string;
            editor_toolbar?: {
                /** Dock position for the Editor Menu and Toolbar. Defaults to 'auto'. */
                dock?: 'auto' | 'bottom' | 'top_offset' | 'top';
                /** Whether to display the editor menu. Defaults to true. */
                show_menu?: boolean;
                /** Whether to display the editor toolbar. Defaults to true. */
                show_toolbar?: boolean;
            };
            /** Editable area type. Defaults to 'htmleditor' */
            type?: 'htmleditor' | 'text';
        };
    };
    /**
     * Default value for each content area.  If omitted,
     * the HTML content will be used.
     */
    default_content?: {
        [content_area_name: string]: string;
    };
    /** Page Properties fields */
    properties?: {
        fields: unknown[];
    };
    options?: {
        /**  If set to false, no cms-title element required on the page. Defaults to true. */
        title_element_required?: boolean;
        /** Page toolbar dock position. Defaults to 'top_offset'. */
        dock?: 'bottom' | 'top_offset' | 'top';
    };
    /** SYSTEM - Hard-coded content element content. */
    content?: {
        [content_area_name: string]: string | {
            title?: string;
        };
    };
}

/**
 * @public
 */
export declare interface JshCmsPageConfigProps {
    config?: JshCmsPageConfigDefinition;
}

/**
 * @public
 */
export declare interface JshCmsPageRequest {
    /** CMS content URL */
    contentUrl: string;
    /** default document if not in url, e.g. 'index.html' */
    defaultDocument: string;
    /** valid CMS server URLs */
    cmsServerUrls: string[];
    /** cache duration in seconds */
    cacheDuration: number;
}

/**
 * @public
 */
export declare interface JshCmsProps {
    jshCmsConfig: JshCmsConfig;
    jshCmsPage?: JshCmsPage;
    children?: React_2.ReactNode;
}

/**
 * @public
 */
export declare function JshCmsProvider(props: JshCmsProviderProps): React_2.JSX.Element;

/**
 * @public
 */
export declare interface JshCmsProviderProps {
    jshCmsConfig?: JshCmsConfig;
    jshCmsPage?: JshCmsPage;
    children?: React_2.ReactNode;
}

/**
 * A redirect loaded from the CMS data file
 * @public
 */
export declare interface JshCmsRedirect {
    redirect_key: number;
    redirect_url: string;
    /** 'BEGINS'|'BEGINSICASE'|'EXACT'|'EXACTICASE'|'REGEX'|'REGEXICASE' */
    redirect_url_type: string;
    redirect_dest: string;
    /** '301'|'302'|'PASSTHRU' */
    redirect_http_code: string;
}

/**
 * Resolved redirect result
 * @public
 */
export declare interface JshCmsRoute {
    /** '301'|'302'|'PASSTHRU' */
    http_code: string;
    url: string;
}

/**
 * @public
 */
export declare class JshCmsRouter {
    /** URL to published CMS content files */
    contentUrl: string;
    /** Path to redirect listing JSON file (relative to contentUrl) */
    redirectListingPath: string | null;
    /** The CMS Server URLs that will be enabled for Page Editing (set to '*' to enable any remote CMS)
     * - Used by jshCmsPage.editorScriptPath, and the getEditorScriptPath function
     * - NOT used by jsHarmonyCmsEditor.js - the launcher instead uses accessKeys for validating the remote CMS
     */
    cmsServerUrls: string[];
    /** Default Directory Document (e.g. index.html) */
    defaultDocument: string;
    /** Cache duration (seconds) */
    cacheDuration: number;
    constructor(config: JshCmsConfig);
    /** getConfig - Get the current config */
    getConfig(): JshCmsConfig;
    /** getRedirectListingPath - Get the configured path for the redirect listing file */
    getRedirectListingPath(): string | undefined;
    /**
     * getRedirectData - Get CMS Redirect Data
     * @param origin - http origin
     * @returns Redirects
     */
    getRedirectData(origin: string): Promise<JshCmsRedirect[]>;
    /**
     * getRedirect - Lookup the redirect for a request, if any
     * @param request - Request object providing target path and origin
     * @returns Appropriate redirect, if one was found
     */
    getRedirect(request: NextRequest): Promise<JshCmsRoute | undefined>;
    /**
     * processJshCmsRedirects - Execute the redirect for a request, if any
     * @param request - Request object providing target path and origin
     * @returns Appropriate response, if one was found
     */
    processRedirects(request: NextRequest): Promise<NextResponse | undefined>;
    /**
     *hasPage - Check if a page object file exists to decide if a route is available.
     * @param pathname - target path
     */
    hasPage(pathname: string): Promise<boolean>;
    /**
     * getStandalonePage [Main Entry Point] - Get CMS Page Data for Standalone Integration
     * @remarks
     * if page is opened from CMS Editor or Not Found, an empty Page Object will be returned
     *
     * @param pathname - Root relative path being requested
     * @param params - Request url parameters
     * @returns Page Object, with filled properties: isInEditor, editorScriptPath, notFound
     */
    getStandalonePage(pathname: string[] | string | undefined, params: {
        [key: string]: string[] | string | undefined;
    }): Promise<JshCmsPage>;
    /**
     * getEmptyPage - An empty Page object, for blank editors or initializing useState
     * @param pageTemplateId - page template id for newly created pages
     */
    getEmptyPage(pageTemplateId: string): JshCmsPage;
    /**
     * getMetadata - provides a basic version of a Next.js metadata function that provides CMS SEO data.
     * @remarks
     * If you application has additional metadata needs, you may wish to copy the base function into your generateMetadata function.
     * {@link https://nextjs.org/docs/app/api-reference/functions/generate-metadata}
     */
    getMetadata({ params }: JshCmsMetadataProps, parent: ResolvingMetadata): Promise<Metadata>;
    /**
     *getPage - Returns a Page object for a specified path
     * @param pathname - Root relative path being requested
     * @param params - Request url parameters
     * @returns Page Object, with filled properties: isInEditor, editorScriptPath, notFound
     */
    getPage(pathname: string[] | string | undefined, params: {
        [key: string]: string[] | string | undefined;
    }): Promise<JshCmsPage>;
    /**
     *serve [Main Entry Point] - Serves CMS content for a target URL
     * @remarks
     * if page is opened from CMS Editor or Not Found, an empty Page Object will be returned
     *
     * @param pathname - Root relative path being requested
     * @param params - Request url parameters
     * @returns Page Object, with filled properties: isInEditor, editorScriptPath, notFound
     */
    serve(pathname: string[] | string | undefined, params: {
        [key: string]: string[] | string | undefined;
    }): Promise<GetServerSidePropsResult<{
        jshCmsPage: JshCmsPage;
    }>>;
    /**
     * loadRedirectData - Load and parse the redirects file
     * @param redirectListingPath - Path to exported CMS redirects
     * @returns List of redirects
     * @public
     */
    loadRedirectData(redirectListingPath: string, origin: string): Promise<JshCmsRedirect[]>;
    /**
     * processRoute - Provides simple handling of redirects in Next.js, replace as needed.
     * @param route - Path and code of a found redirect
     * @param requestUrl - Original request url
     * @returns Response, if a valid redirect was provided.
     * @public
     */
    static processRoute(route: JshCmsRoute, requestUrl: URL | string | undefined): NextResponse | undefined;
    /**
     * matchRedirect - Check if URL matches redirects and return first match
     * @param redirects - Array of CMS Redirects
     * @param urlpath - Target URL path
     * @public
     */
    static matchRedirect(redirects: JshCmsRedirect[], urlpath: string): JshCmsRoute | undefined;
    /**
     * getRedirectBase - Looks up matching redirect, if any.
     * @param pathname - target path
     * @param contentUrl - URL to content files
     * @param redirectListingPath - Path to exported CMS redirects
     * @returns path and code if found
     */
    private getRedirectBase;
    /**
     * hasPageBase - Check if a page object file exists to decide if a route is available.
     * @param pathname - target url path name
     * @param contentUrl - URL to CMS content files
     * @param defaultDocument - default document if not in url, e.g. 'index.html'
     */
    private hasPageBase;
}

/**
 * JshCmsScript - render additional javascript (if any) as a script tag
 * @remarks
 * Simple React function component for conditionally including tags in pages. These are trivial and can be replaced with custom code as needed.
 * Note: CMS was designed to support additional head tags. Next.js takes full control of the head, so these must be placed elsewhere.
 *
 * @example
 * ```
 * <JshCmsScript jshCmsPage={jshCmsPage} />
 * ```
 * @public
 */
export declare function JshCmsScript(props: JshCmsElementProps): React_2.JSX.Element;

/**
 * JshCmsStyle - render additional css (if any) as a style tag
 * @remarks
 * Simple React function component for conditionally including tags in pages. These are trivial and can be replaced with custom code as needed.
 * Note: CMS was designed to support additional head tags. Next.js takes full control of the head, so these must be placed elsewhere.
 *
 * @example
 * ```
 * <JshCmsStyle jshCmsPage={jshCmsPage} />
 * ```
 * @public
 */
export declare function JshCmsStyle(props: JshCmsElementProps): React_2.JSX.Element;

/**
 * @internal
 */
export declare interface notifyUpdateProps {
    element: HTMLElement;
    componentId: string;
    contentAreaName: string;
    data?: unknown;
    properties?: unknown;
    isItemPreview?: boolean;
    isGridRowPreview?: boolean;
    content?: string;
}

/**
 * @public
 */
export declare const useJshCms: () => JshCmsContextData;

/**
 * @public
 */
export declare function useJshCmsPageComponentData<T>(props: {
    jshCmsPage?: JshCmsPage;
    componentId: string;
    contentAreaName?: string;
}): {
    componentData: (T | null);
};

export { }
