import { ConfigEnv, Plugin, PluginOption } from 'vite';
import { IsStringLiteral } from 'type-fest';
import { Options } from 'fast-glob';
import { PluginContext, OutputBundle } from 'rollup';

interface DeclarativeNetRequestResource {
    id: string;
    enabled: boolean;
    path: string;
}
interface WebAccessibleResourceByMatch {
    matches: string[];
    resources: string[];
    use_dynamic_url?: boolean;
}
interface WebAccessibleResourceById {
    extension_ids: string[];
    resources: string[];
    use_dynamic_url?: boolean;
}
interface ChromeManifestBackground {
    service_worker: string;
    type?: 'module' | (string & {});
}
interface FirefoxManifestBackground {
    scripts: string[];
    persistent?: false;
}
interface ManifestV3 {
    manifest_version: number;
    name: string;
    version: string;
    default_locale?: string | undefined;
    description?: string | undefined;
    icons?: chrome.runtime.ManifestIcons | undefined;
    action?: chrome.runtime.ManifestAction | undefined;
    /**
     * @see https://developer.chrome.com/docs/extensions/reference/manifest/author
     */
    author?: {
        email: string;
    } | undefined;
    background?: ChromeManifestBackground | FirefoxManifestBackground | undefined;
    chrome_settings_overrides?: {
        homepage?: string | undefined;
        search_provider?: chrome.runtime.SearchProvider | undefined;
        startup_pages?: string[] | undefined;
    } | undefined;
    chrome_ui_overrides?: {
        bookmarks_ui?: {
            remove_bookmark_shortcut?: boolean | undefined;
            remove_button?: boolean | undefined;
        } | undefined;
    } | undefined;
    chrome_url_overrides?: {
        bookmarks?: string | undefined;
        history?: string | undefined;
        newtab?: string | undefined;
    } | undefined;
    commands?: {
        [name: string]: {
            suggested_key?: {
                default?: string | undefined;
                windows?: string | undefined;
                mac?: string | undefined;
                chromeos?: string | undefined;
                linux?: string | undefined;
            } | undefined;
            description?: string | undefined;
            global?: boolean | undefined;
        };
    } | undefined;
    content_capabilities?: {
        matches?: string[] | undefined;
        permissions?: string[] | undefined;
    } | undefined;
    content_scripts?: {
        matches?: string[] | undefined;
        exclude_matches?: string[] | undefined;
        css?: string[] | undefined;
        js?: string[] | undefined;
        run_at?: string | undefined;
        all_frames?: boolean | undefined;
        match_about_blank?: boolean | undefined;
        include_globs?: string[] | undefined;
        exclude_globs?: string[] | undefined;
        world?: chrome.scripting.ExecutionWorld | string | undefined;
    }[] | undefined;
    content_security_policy?: {
        extension_pages?: string;
        sandbox?: string;
    };
    converted_from_user_script?: boolean | undefined;
    current_locale?: string | undefined;
    declarative_net_request?: {
        rule_resources: DeclarativeNetRequestResource[];
    };
    devtools_page?: string | undefined;
    event_rules?: {
        event?: string | undefined;
        actions?: {
            type: string;
        }[] | undefined;
        conditions?: chrome.declarativeContent.PageStateMatcherProperties[] | undefined;
    }[] | undefined;
    externally_connectable?: {
        ids?: string[] | undefined;
        matches?: string[] | undefined;
        accepts_tls_channel_id?: boolean | undefined;
    } | undefined;
    file_browser_handlers?: {
        id?: string | undefined;
        default_title?: string | undefined;
        file_filters?: string[] | undefined;
    }[] | undefined;
    file_system_provider_capabilities?: {
        configurable?: boolean | undefined;
        watchable?: boolean | undefined;
        multiple_mounts?: boolean | undefined;
        source?: string | undefined;
    } | undefined;
    homepage_url?: string | undefined;
    host_permissions?: string[] | undefined;
    import?: {
        id: string;
        minimum_version?: string | undefined;
    }[] | undefined;
    export?: {
        whitelist?: string[] | undefined;
    } | undefined;
    incognito?: string | undefined;
    input_components?: {
        name: string;
        id?: string | undefined;
        language?: string | string[] | undefined;
        layouts?: string | string[] | undefined;
        input_view?: string | undefined;
        options_page?: string | undefined;
    }[] | undefined;
    key?: string | undefined;
    minimum_chrome_version?: string | undefined;
    nacl_modules?: {
        path: string;
        mime_type: string;
    }[] | undefined;
    oauth2?: {
        client_id: string;
        scopes?: string[] | undefined;
    } | undefined;
    offline_enabled?: boolean | undefined;
    omnibox?: {
        keyword: string;
    } | undefined;
    optional_host_permissions?: string[] | undefined;
    optional_permissions?: chrome.runtime.ManifestPermissions[] | string[] | undefined;
    options_page?: string | undefined;
    options_ui?: {
        page?: string | undefined;
        chrome_style?: boolean | undefined;
        open_in_tab?: boolean | undefined;
    } | undefined;
    permissions?: chrome.runtime.ManifestPermissions[] | string[] | undefined;
    platforms?: {
        nacl_arch?: string | undefined;
        sub_package_path: string;
    }[] | undefined;
    plugins?: {
        path: string;
    }[] | undefined;
    requirements?: {
        '3D'?: {
            features?: string[] | undefined;
        } | undefined;
        plugins?: {
            npapi?: boolean | undefined;
        } | undefined;
    } | undefined;
    sandbox?: {
        pages: string[];
        content_security_policy?: string | undefined;
    } | undefined;
    side_panel?: {
        default_path?: string | undefined;
    } | undefined;
    short_name?: string | undefined;
    spellcheck?: {
        dictionary_language?: string | undefined;
        dictionary_locale?: string | undefined;
        dictionary_format?: string | undefined;
        dictionary_path?: string | undefined;
    } | undefined;
    storage?: {
        managed_schema: string;
    } | undefined;
    tts_engine?: {
        voices: {
            voice_name: string;
            lang?: string | undefined;
            gender?: string | undefined;
            event_types?: string[] | undefined;
        }[];
    } | undefined;
    update_url?: string | undefined;
    version_name?: string | undefined;
    web_accessible_resources?: (WebAccessibleResourceById | WebAccessibleResourceByMatch)[] | undefined;
    browser_specific_settings?: {
        gecko: {
            id: string;
            strict_min_version?: string | undefined;
            strict_max_version?: string | undefined;
            update_url?: string | undefined;
            data_collection_permissions: {
                /**
                 * available value: "personallyIdentifyingInfo" | "healthInfo" | "financialAndPaymentInfo" | "authenticationInfo" | "personalCommunications" | "locationInfo" | "browsingActivity" | "websiteContent" | "websiteActivity" | "searchTerms" | "bookmarksInfo" | "none".
                 * see also: https://extensionworkshop.com/documentation/develop/firefox-builtin-data-consent/
                */
                required: GeckoPermissionsRequired[];
                /**
                 * available value: "personallyIdentifyingInfo" | "healthInfo" | "financialAndPaymentInfo" | "authenticationInfo" | "personalCommunications" | "locationInfo" | "browsingActivity" | "websiteContent" | "websiteActivity" | "searchTerms" | "bookmarksInfo" | "technicalAndInteraction".
                 * see also: https://extensionworkshop.com/documentation/develop/firefox-builtin-data-consent/
                */
                optional?: GeckoPermissionsOptional[] | undefined;
            };
        };
    } | undefined;
}
type GeckoPermissionsRequired = "personallyIdentifyingInfo" | "healthInfo" | "financialAndPaymentInfo" | "authenticationInfo" | "personalCommunications" | "locationInfo" | "browsingActivity" | "websiteContent" | "websiteActivity" | "searchTerms" | "bookmarksInfo" | "none";
type GeckoPermissionsOptional = "personallyIdentifyingInfo" | "healthInfo" | "financialAndPaymentInfo" | "authenticationInfo" | "personalCommunications" | "locationInfo" | "browsingActivity" | "websiteContent" | "websiteActivity" | "searchTerms" | "bookmarksInfo" | "technicalAndInteraction";

type ManifestV3Fn = (env: ConfigEnv) => ManifestV3 | Promise<ManifestV3>;
type ManifestV3Export = ManifestV3 | Promise<ManifestV3> | ManifestV3Fn;
type Code = '.' | '/' | '\\';
type LiteralManifestFilePath<T extends string> = T extends `${Code}${string}` ? never : T extends `${string}.${infer Ext}` ? Ext extends '' ? never : T : never;
type ManifestFilePath<T extends string> = IsStringLiteral<T> extends true ? LiteralManifestFilePath<T> : T;
interface ManifestIcons<T extends string> {
    [size: number]: ManifestFilePath<T>;
}
type FilePathFields<T extends string> = {
    icons?: ManifestIcons<T>;
    action?: {
        /**
         * - Relative to Vite project root (where vite.config.js is)
         * - Format: "subdir/icon.png" (no leading ./ or /)
         *
         * @example "assets/icon.png"
         */
        default_icon?: ManifestIcons<T>;
        default_title?: string;
        /**
         * - Relative to Vite project root (where vite.config.js is)
         * - Format: "subdir/index.html" (no leading ./ or /)
         *
         * @example "src/popup.html"
         */
        default_popup?: ManifestFilePath<T>;
    };
    background?: {
        /**
         * - Relative to Vite project root (where vite.config.js is)
         * - Format: "subdir/index.js" (no leading ./ or /)
         *
         * @example "src/background.js"
         */
        service_worker: ManifestFilePath<T>;
        type?: 'module' | (string & {});
    } | FirefoxManifestBackground;
    content_scripts?: {
        matches?: string[];
        exclude_matches?: string[];
        /**
         * - Relative to Vite project root (where vite.config.js is)
         * - Format: "subdir/content.css" (no leading ./ or /)
         *
         * @example "src/content.css"
         */
        css?: ManifestFilePath<T>[];
        /**
         * - Relative to Vite project root (where vite.config.js is)
         * - Format: "subdir/content.js" (no leading ./ or /)
         *
         * @example "src/content.js"
         */
        js?: ManifestFilePath<T>[];
        run_at?: string;
        all_frames?: boolean;
        match_about_blank?: boolean;
        include_globs?: string[];
        exclude_globs?: string[];
        /**
         * - 'ISOLATED' (default): Content script runs in an isolated world.
         * - 'MAIN': Content script runs in the main world.
         * NOTE: MAIN currently does NOT support crxjs HMR
         * @see https://developer.chrome.com/docs/extensions/mv3/content_scripts/#world
         */
        world?: 'ISOLATED' | 'MAIN';
    }[];
    input_components?: {
        name: string;
        id?: string;
        language?: string | string[];
        layouts?: string | string[];
        input_view?: string;
        /**
         * - Relative to Vite project root (where vite.config.js is)
         * - Format: "subdir/options.html" (no leading ./ or /)
         *
         * @example "src/options.html"
         */
        options_page?: ManifestFilePath<T>;
    }[];
    /**
     * - Relative to Vite project root (where vite.config.js is)
     * - Format: "subdir/options.html" (no leading ./ or /)
     *
     * @example "src/options.html"
     */
    options_page?: ManifestFilePath<T>;
    /**
     * - Relative to Vite project root (where vite.config.js is)
     * - Format: "subdir/devtools.html" (no leading ./ or /)
     *
     * @example "src/devtools.html"
     */
    devtools_page?: ManifestFilePath<T>;
};
type ManifestOptions<T extends string> = Omit<ManifestV3, keyof FilePathFields<string>> & FilePathFields<T>;
type ManifestV3Options<T extends string = string> = ManifestOptions<T> | Promise<ManifestOptions<T>> | ManifestV3Define<T>;
type ManifestV3Define<T extends string> = (env: ConfigEnv) => ManifestOptions<T> | Promise<ManifestOptions<T>>;
declare const defineManifest: <T extends string>(manifest: ManifestV3Options<T>) => ManifestV3Export;
/**
 * Content script resources like CSS and image files must be declared in the
 * manifest under `web_accessible_resources`. Manifest V3 uses a match pattern
 * to narrow the origins that can access a Chrome CRX resource.
 *
 * Content script resources use the same match pattern as the content script for
 * web accessible resources.
 *
 * You don't need to define a match pattern for dynamic content script
 * resources, but if you want to do so, you can use the helper function
 * `defineDynamicResource` to define your web accessible resources in a
 * TypeScript file:
 *
 * ```typescript
 * import { crx, defineManifest, defineDynamicResource }
 * const manifest = defineManifest({
 *   "web_accessible_resources": [
 *     defineDynamicResource({
 *       matches: ["https://example.com/*", "file:///*.mp3", "..."]
 *       use_dynamic_url?: true
 *     })
 *   ]
 * })
 * ```
 */
declare const defineDynamicResource: ({ matches, use_dynamic_url, }: Omit<WebAccessibleResourceByMatch, 'resources'>) => WebAccessibleResourceByMatch;

type CrxDevAssetId = {
    id: string;
    type: 'asset';
    source?: string | Uint8Array;
};
type CrxDevScriptId = {
    id: string;
    type: 'module' | 'iife';
};
interface CrxPlugin extends Plugin {
    /**
     * Runs during the transform hook for the manifest. Filenames use input
     * filenames.
     */
    transformCrxManifest?: (this: PluginContext, manifest: ManifestV3) => Promise<ManifestV3 | null | undefined> | ManifestV3 | null | undefined;
    /**
     * Runs during generateBundle, before manifest output. Filenames use output
     * filenames.
     */
    renderCrxManifest?: (this: PluginContext, manifest: ManifestV3, bundle: OutputBundle) => Promise<ManifestV3 | null | undefined> | ManifestV3 | null | undefined;
    /**
     * Runs in the file writer on content scripts during development. `script.id`
     * is Vite URL format.
     */
    renderCrxDevScript?: (code: string, script: CrxDevScriptId) => Promise<string | null | undefined> | string | null | undefined;
}
interface CrxOptions {
    contentScripts?: {
        preambleCode?: string | false;
        hmrTimeout?: number;
        injectCss?: boolean;
    };
    fastGlobOptions?: Options;
    /**
     * The browser that this extension is targeting, can be "firefox" or "chrome".
     * Default is "chrome".
     */
    browser?: Browser;
}
type Browser = 'firefox' | 'chrome';

/** Resolves when all existing files in scriptFiles are written. */
declare function allFilesReady(): Promise<void>;

type FileWriterId = {
    type: CrxDevAssetId['type'] | CrxDevScriptId['type'] | 'loader';
    id: string;
};
/** Resolves when file and dependencies are written. */
declare function fileReady(script: FileWriterId): Promise<void>;

declare const crx: (options: {
    manifest: ManifestV3Export;
} & CrxOptions) => PluginOption[];
declare const chromeExtension: (options: {
    manifest: ManifestV3Export;
} & CrxOptions) => PluginOption[];

export { CrxPlugin, ManifestV3Export, allFilesReady, chromeExtension, crx, defineDynamicResource, defineManifest, fileReady as filesReady };
