"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const puppeteer_extra_1 = __importDefault(require("puppeteer-extra"));
/** @inheritdoc */
class PuppeteerService {
    /** @inheritdoc */
    async getUserAgent() {
        return await this.puppeteerInstance?.browser.userAgent() ?? "unknown";
    }
    /** @inheritdoc */
    constructor(logger) {
        this.logger = logger;
    }
    async recreateInstance() {
        if (this.puppeteerInstance != undefined) {
            await this.dispose();
        }
        this.puppeteerInstance = await this.initializePuppeteer();
    }
    /** @inheritdoc */
    async isHealthy() {
        try {
            const browser = this.puppeteerInstance?.browser;
            const page = this.puppeteerInstance?.page;
            if (!browser || !page)
                return false;
            if (!browser.connected)
                return false;
            if (page.isClosed())
                return false;
            const pages = await browser.pages();
            return pages.some(p => p === page);
        }
        catch { //any way for me to throw an error above that will result in this try catch firing?
            return false;
        }
    }
    /** @inheritdoc */
    async getInstance() {
        if (!(await this.isHealthy())) {
            await this.recreateInstance();
        }
        if (!this.puppeteerInstance) {
            throw new Error("Puppeteer instance in irrecoverable state");
        }
        return this.puppeteerInstance;
    }
    async initializePuppeteer() {
        this.logger.info("initializing puppeteer");
        // avoid detection
        // eslint-disable-next-line @typescript-eslint/no-require-imports
        const StealthPlugin = require('puppeteer-extra-plugin-stealth');
        try {
            puppeteer_extra_1.default.use(StealthPlugin());
            // Launch the browser and open a new blank page
            const browser = await puppeteer_extra_1.default.launch({
                headless: false,
                args: ["--mute-audio"]
            });
            // set up the web page
            const page = (await browser.pages())[0];
            await page.emulateMediaFeatures([
                { name: "prefers-color-scheme", value: "light" },
            ]);
            // Catch errors
            browser.on('disconnected', () => {
                this.logger.warn('Browser disconnected unexpectedly!');
            });
            page.on("pageerror", err => {
                this.logger.info(`Page error: ${err}`);
            });
            return { browser: browser, page: page }; //is there any reason puppeteer would shut itself down here?
        }
        catch (error) {
            throw new Error(`Puppeteer instance could not be created: ${String(error)}`);
        }
    }
    async dispose() {
        if (!this.puppeteerInstance) {
            this.logger.warn("Existing Puppeteer instance not found, could not reset.");
            return;
        }
        const { page, browser } = this.puppeteerInstance;
        if (page) {
            try {
                await page.close();
            }
            catch (error) {
                this.logger.warn(String(error));
            }
        }
        if (browser) {
            try {
                await browser.close();
            }
            catch (error) {
                this.logger.warn(String(error));
            }
        }
        this.puppeteerInstance = undefined;
    }
}
exports.default = PuppeteerService;
//# sourceMappingURL=puppeteer_service.js.map