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 __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
    if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
    if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
    return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
    if (kind === "m") throw new TypeError("Private method is not writable");
    if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
    if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
    return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var _DevvitBlocksWebView_instances, _DevvitBlocksWebView_hasLoaded, _DevvitBlocksWebView_queuedMessages, _DevvitBlocksWebView_sandboxUpdated, _DevvitBlocksWebView_resolveSandboxUpdated, _DevvitBlocksWebView_clearQueue, _DevvitBlocksWebView_handleMessage, _DevvitBlocksWebView_sendStateUpdate, _DevvitBlocksWebView_onLoad, _DevvitBlocksWebView_postDevvitMessage, _DevvitBlocksWebView_debugLog;
import {} from '@devvit/protos/types/devvit/ui/effects/web_view/v1alpha/post_message.js';
import { customEvent } from '@reddit/faceplate/lib/custom-event.js';
import { css, html, LitElement } from 'lit';
import { customElement, property, query, state } from 'lit/decorators.js';
import { ifDefined } from 'lit/directives/if-defined.js';
/**
 * Wraps an iframe to capture messages sent from within to be handled by the app rendering the Blocks
 */
let DevvitBlocksWebView = class DevvitBlocksWebView extends LitElement {
    constructor() {
        super(...arguments);
        _DevvitBlocksWebView_instances.add(this);
        this.devMode = false;
        this._originDiffers = false; // eslint-disable-line @typescript-eslint/naming-convention
        _DevvitBlocksWebView_hasLoaded.set(this, false);
        _DevvitBlocksWebView_queuedMessages.set(this, []);
        _DevvitBlocksWebView_sandboxUpdated.set(this, void 0);
        _DevvitBlocksWebView_resolveSandboxUpdated.set(this, () => { });
        /**
         * Iframe will post messages to the window, we'll capture that and re-emit from here
         * so we can handle messages locally
         * @param event
         * @private
         */
        _DevvitBlocksWebView_handleMessage.set(this, (event) => {
            if (event.source === this._iframe?.contentWindow) {
                __classPrivateFieldGet(this, _DevvitBlocksWebView_instances, "m", _DevvitBlocksWebView_debugLog).call(this, 'Got message from iframe:', event.data);
                event.preventDefault();
                event.stopImmediatePropagation();
                this.dispatchEvent(customEvent('devvit-web-view-message', event.data));
            }
        });
    }
    static get styles() {
        return [
            css `
        :host {
          display: flex;
          flex-direction: row;
        }

        iframe {
          flex-grow: 1;
          border: 0;
          max-width: 100%;
          max-height: 100%;
        }
      `,
        ];
    }
    connectedCallback() {
        super.connectedCallback();
        window.addEventListener('message', __classPrivateFieldGet(this, _DevvitBlocksWebView_handleMessage, "f"));
    }
    disconnectedCallback() {
        super.disconnectedCallback();
        window.removeEventListener('message', __classPrivateFieldGet(this, _DevvitBlocksWebView_handleMessage, "f"));
    }
    async getUpdateComplete() {
        const result = super.getUpdateComplete();
        await __classPrivateFieldGet(this, _DevvitBlocksWebView_sandboxUpdated, "f");
        return result;
    }
    willUpdate(changedProperties) {
        if (changedProperties.has('state') && this.state) {
            __classPrivateFieldGet(this, _DevvitBlocksWebView_instances, "m", _DevvitBlocksWebView_sendStateUpdate).call(this);
        }
        if (changedProperties.has('src') && this.src) {
            const url = new URL(this.src);
            // Only send messages to app domains
            if (url.hostname.endsWith('webview.devvit.net')) {
                this._targetOrigin = url.origin;
            }
            else if (this.devMode) {
                this._targetOrigin = '*';
            }
            else {
                // not passing a target defaults to the current Origin
                this._targetOrigin = undefined;
            }
            __classPrivateFieldSet(this, _DevvitBlocksWebView_hasLoaded, false, "f");
            if (changedProperties.get('src')) {
                __classPrivateFieldGet(this, _DevvitBlocksWebView_instances, "m", _DevvitBlocksWebView_clearQueue).call(this);
            }
            __classPrivateFieldGet(this, _DevvitBlocksWebView_instances, "m", _DevvitBlocksWebView_debugLog).call(this, 'New configuration: src:', this.src, '; allow-same-origin:', this._originDiffers, '; targetOrigin: ', this._targetOrigin);
        }
    }
    updated(_changedProperties) {
        // Update `_originDiffers` in `updated` instead of `willUpdate` so the
        // change triggers another update. If we set the URL on the same frame
        // that we update the sandbox, the first page won't get the updated
        // permissions. If we did change the sandbox settings, `src` is saved
        // in another stateful variable that will trigger another update, allowing
        // the sandbox to be updated without setting the src this frame. If we
        // don't delay then allow-same-origin is not ready and the frame does not
        // have an origin in which to receive targeted messages.
        if (_changedProperties.has('src') && this.src) {
            const url = new URL(this.src);
            // If true, applies `allow-same-origin` to the iframe but removes it
            // if the URL matches the host to protect the main window from the
            // contents of the iframe reaching out of the sandbox
            const originDiffers = url.host !== location.host;
            if (originDiffers !== this._originDiffers) {
                this._originDiffers = originDiffers;
                this.pendingSrc = this.src;
                this.src = undefined;
                // Setup a promise to delay `updateComplete` until we've finished applying the updated sandbox and src settings
                __classPrivateFieldSet(this, _DevvitBlocksWebView_sandboxUpdated, new Promise((resolve) => (__classPrivateFieldSet(this, _DevvitBlocksWebView_resolveSandboxUpdated, resolve, "f"))), "f");
            }
        }
        // `_pendingSrc` was updated last frame, so reapply it to `src` now that
        // the sandbox settings have settled.
        if (_changedProperties.has('pendingSrc') && this.pendingSrc) {
            this.src = this.pendingSrc;
            this.pendingSrc = undefined;
            __classPrivateFieldGet(this, _DevvitBlocksWebView_resolveSandboxUpdated, "f").call(this);
        }
    }
    reset() {
        __classPrivateFieldGet(this, _DevvitBlocksWebView_instances, "m", _DevvitBlocksWebView_clearQueue).call(this);
    }
    postMessage(message) {
        if (!__classPrivateFieldGet(this, _DevvitBlocksWebView_hasLoaded, "f")) {
            // don't send messages until we've received the onload event from the iframe
            __classPrivateFieldGet(this, _DevvitBlocksWebView_queuedMessages, "f").push(message);
            __classPrivateFieldGet(this, _DevvitBlocksWebView_instances, "m", _DevvitBlocksWebView_debugLog).call(this, () => ['Not ready. Queueing message:', JSON.stringify(message)]);
        }
        else {
            __classPrivateFieldGet(this, _DevvitBlocksWebView_instances, "m", _DevvitBlocksWebView_postDevvitMessage).call(this, 'devvit-message', message);
        }
    }
    render() {
        // Only allow the page to run in `same origin` mode if it's different from ours
        const allowOrigin = this._originDiffers ? 'allow-same-origin' : '';
        return html `<iframe
      src="${ifDefined(this.src)}"
      sandbox="allow-scripts ${allowOrigin}"
      referrerpolicy="origin"
      @load="${__classPrivateFieldGet(this, _DevvitBlocksWebView_instances, "m", _DevvitBlocksWebView_onLoad)}"
    ></iframe>`;
    }
};
_DevvitBlocksWebView_hasLoaded = new WeakMap();
_DevvitBlocksWebView_queuedMessages = new WeakMap();
_DevvitBlocksWebView_sandboxUpdated = new WeakMap();
_DevvitBlocksWebView_resolveSandboxUpdated = new WeakMap();
_DevvitBlocksWebView_handleMessage = new WeakMap();
_DevvitBlocksWebView_instances = new WeakSet();
_DevvitBlocksWebView_clearQueue = function _DevvitBlocksWebView_clearQueue() {
    __classPrivateFieldGet(this, _DevvitBlocksWebView_instances, "m", _DevvitBlocksWebView_debugLog).call(this, 'WebView reset. Clearing queued messages:', __classPrivateFieldGet(this, _DevvitBlocksWebView_queuedMessages, "f").length);
    __classPrivateFieldGet(this, _DevvitBlocksWebView_queuedMessages, "f").length = 0;
};
_DevvitBlocksWebView_sendStateUpdate = function _DevvitBlocksWebView_sendStateUpdate() {
    if (this.state && __classPrivateFieldGet(this, _DevvitBlocksWebView_hasLoaded, "f")) {
        const stateMessage = {
            state: this.state,
        };
        __classPrivateFieldGet(this, _DevvitBlocksWebView_instances, "m", _DevvitBlocksWebView_postDevvitMessage).call(this, 'devvit-state', stateMessage);
        __classPrivateFieldGet(this, _DevvitBlocksWebView_instances, "m", _DevvitBlocksWebView_postDevvitMessage).call(this, 'stateUpdate', this.state);
    }
};
_DevvitBlocksWebView_onLoad = function _DevvitBlocksWebView_onLoad() {
    if (!__classPrivateFieldGet(this, _DevvitBlocksWebView_hasLoaded, "f") && this.src) {
        __classPrivateFieldGet(this, _DevvitBlocksWebView_instances, "m", _DevvitBlocksWebView_debugLog).call(this, 'Page loaded. Sending initial state.');
        __classPrivateFieldSet(this, _DevvitBlocksWebView_hasLoaded, true, "f");
        // ensure we send a state update at least once
        __classPrivateFieldGet(this, _DevvitBlocksWebView_instances, "m", _DevvitBlocksWebView_sendStateUpdate).call(this);
        __classPrivateFieldGet(this, _DevvitBlocksWebView_instances, "m", _DevvitBlocksWebView_debugLog).call(this, 'Sending', __classPrivateFieldGet(this, _DevvitBlocksWebView_queuedMessages, "f").length, 'queued messages');
        for (const message of __classPrivateFieldGet(this, _DevvitBlocksWebView_queuedMessages, "f")) {
            __classPrivateFieldGet(this, _DevvitBlocksWebView_instances, "m", _DevvitBlocksWebView_postDevvitMessage).call(this, 'devvit-message', message);
        }
    }
};
_DevvitBlocksWebView_postDevvitMessage = function _DevvitBlocksWebView_postDevvitMessage(type, data) {
    const postMessage = {
        type,
        data,
    };
    const postOptions = this._targetOrigin ? { targetOrigin: this._targetOrigin } : {};
    this._iframe?.contentWindow?.postMessage(postMessage, postOptions);
    __classPrivateFieldGet(this, _DevvitBlocksWebView_instances, "m", _DevvitBlocksWebView_debugLog).call(this, () => ['Sending message:', JSON.stringify(postMessage)]);
};
_DevvitBlocksWebView_debugLog = function _DevvitBlocksWebView_debugLog(msg) {
    if (globalThis.devvit?.debug.webView) {
        console.log.apply(null, [
            `[webView${this.id ? `#${this.id}` : ''}]`,
            ...(typeof msg === 'function' ? msg() : typeof msg === 'string' ? [msg] : msg),
        ]);
    }
};
__decorate([
    property({ type: String }),
    __metadata("design:type", Object)
], DevvitBlocksWebView.prototype, "src", void 0);
__decorate([
    property({ type: Boolean, attribute: 'dev-mode' }),
    __metadata("design:type", Boolean)
], DevvitBlocksWebView.prototype, "devMode", void 0);
__decorate([
    property({ attribute: false }),
    __metadata("design:type", Object)
], DevvitBlocksWebView.prototype, "state", void 0);
__decorate([
    state(),
    __metadata("design:type", Boolean)
], DevvitBlocksWebView.prototype, "_originDiffers", void 0);
__decorate([
    state(),
    __metadata("design:type", Object)
], DevvitBlocksWebView.prototype, "_targetOrigin", void 0);
__decorate([
    state(),
    __metadata("design:type", Object)
], DevvitBlocksWebView.prototype, "pendingSrc", void 0);
__decorate([
    query('iframe'),
    __metadata("design:type", Object)
], DevvitBlocksWebView.prototype, "_iframe", void 0);
DevvitBlocksWebView = __decorate([
    customElement('devvit-blocks-web-view')
], DevvitBlocksWebView);
export { DevvitBlocksWebView };
//# sourceMappingURL=devvit-blocks-web-view.js.map