"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CheckpointService = void 0;
const inversify_1 = require("inversify");
const exception_js_1 = require("../../exception.js");
const browser_js_1 = require("./browser.js");
const globals_js_1 = require("./globals.js");
let CheckpointService = class CheckpointService {
    constructor(browser, globals) {
        this.browser = browser;
        this.globals = globals;
    }
    get page() {
        return this.browser.page;
    }
    async sendCheckpoint(_checkpointData) { }
    async createCheckpoint(title) {
        await this.page.target.refreshInfo();
        const { url } = this.page.target;
        const cookies = await this.page.getAllCookies();
        const postParams = [...new URLSearchParams(this.page.target.postData || '')];
        const rs = this.page.networkManager.getResourceById(this.page.target.requestId || '');
        const method = rs ? rs.request.method : 'GET';
        const { securityOrigin } = this.page.mainFrame();
        const localStorage = await this.getStorageItems({ securityOrigin, isLocalStorage: true });
        const sessionStorage = await this.getStorageItems({ securityOrigin, isLocalStorage: false });
        const globals = this.globals.values;
        return {
            method,
            url,
            title,
            cookies,
            postParams,
            localStorage,
            sessionStorage,
            globals,
        };
    }
    async restoreCheckpoint(checkpoint) {
        const { cookies = [], localStorage = [], sessionStorage = [], globals = [] } = checkpoint;
        await this.page.clearBrowsingData();
        await this.page.setCookies(cookies);
        await this.page.navigate('about:blank');
        this.globals.values = globals;
        const { identifier } = await this.page.send('Page.addScriptToEvaluateOnNewDocument', {
            source: this.compileStorageRestoreScript(localStorage, sessionStorage),
        });
        await this.performCheckpointNavigation(checkpoint);
        await this.page.send('Page.removeScriptToEvaluateOnNewDocument', { identifier });
    }
    async performCheckpointNavigation(checkpoint) {
        const { url, method = 'get', postParams = [] } = checkpoint;
        switch (method.toLowerCase()) {
            case 'get': {
                await this.page.navigate(url);
                break;
            }
            case 'post': {
                const document = await this.page.document();
                await document.sendPost(url, postParams);
                break;
            }
            default:
                throw new exception_js_1.Exception({
                    name: 'CheckpointRestoreFailed',
                    message: `Unsupported method: ${method}`,
                    retry: false,
                });
        }
    }
    async getStorageItems(storageId) {
        try {
            const data = await this.page.send('DOMStorage.getDOMStorageItems', { storageId });
            return data.entries;
        }
        catch (err) {
            if (err.message.includes('Frame not found')) {
                return [];
            }
            throw err;
        }
    }
    compileStorageRestoreScript(localStorage, sessionStorage) {
        const lines = [];
        for (const [key, value] of localStorage) {
            lines.push(`localStorage.setItem(${JSON.stringify(key)}, ${JSON.stringify(value)});`);
        }
        for (const [key, value] of sessionStorage) {
            lines.push(`sessionStorage.setItem(${JSON.stringify(key)}, ${JSON.stringify(value)});`);
        }
        return lines.join('\n');
    }
};
CheckpointService = __decorate([
    (0, inversify_1.injectable)(),
    __param(0, (0, inversify_1.inject)(browser_js_1.BrowserService)),
    __param(1, (0, inversify_1.inject)(globals_js_1.GlobalsService)),
    __metadata("design:paramtypes", [browser_js_1.BrowserService,
        globals_js_1.GlobalsService])
], CheckpointService);
exports.CheckpointService = CheckpointService;
//# sourceMappingURL=checkpoint.js.map