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 _DevvitCustomPost_instances, _DevvitCustomPost_dispatcher, _DevvitCustomPost_rootHeight, _DevvitCustomPost_resizeObserver, _DevvitCustomPost_intersectionObserver, _DevvitCustomPost_appVersion, _DevvitCustomPost_bubble, _DevvitCustomPost_newRenderContext, _DevvitCustomPost_onError, _DevvitCustomPost_onPluginCall, _DevvitCustomPost_onRenderPost, _DevvitCustomPost_onUserActionEffect;
import '@reddit/faceplate-ui/templateRenderingStrategy/clientStrategy.js';
import { BlockRenderEventType, BlockStackDirection, RealtimeDefinition } from '@devvit/protos';
import { BlockConfig_Root } from '@devvit/protos/types/devvit/ui/block_kit/v1beta/block.js';
import { UIDimensions } from '@devvit/protos/types/devvit/ui/common/v1alpha/common.js';
import { isCircuitBreaker } from '@devvit/shared-types/CircuitBreaker.js';
import { Header } from '@devvit/shared-types/Header.js';
import { throttle } from '@devvit/shared-types/throttle.js';
import { asT3ID } from '@devvit/shared-types/tid.js';
import { customEvent } from '@reddit/faceplate/lib/custom-event.js';
import { html, LitElement } from 'lit';
import { customElement, property, query, state } from 'lit/decorators.js';
import { DevvitBlocksRenderer } from '../blocks/components/devvit-blocks-renderer.js';
import { DEFAULT_ROOT_HEIGHT } from '../blocks/templates/renderBlock.js';
import { styles } from '../styles.js';
import { buildDimensions } from './dimensions.js';
import { Dispatcher } from './dispatcher/dispatcher.js';
import { resolveWebviewUrl } from './webview.js';
import '../blocks/components/devvit-blocks-renderer.js';
import '../blocks/components/devvit-blocks-webview.js';
/**
 * Blocks program renderer.
 *
 * Assumes the loaded program is a CustomPost & UIEventHandler.
 *
 * The complexity of this class should only be the UI itself and proxying state
 * to devvit-blocks-renderer and Dispatcher. Don't put logic here that you can't
 * unit test.
 *
 * @slot - Loading / unloaded state.
 */
let DevvitCustomPost = class DevvitCustomPost extends LitElement {
    static get styles() {
        return [styles];
    }
    constructor() {
        super();
        _DevvitCustomPost_instances.add(this);
        this.runtimeDebugLogging = false;
        this.useExperimentalBlocks = false;
        this.webviewUrlTemplate = '';
        this.disableAssetSandbox = false;
        _DevvitCustomPost_dispatcher.set(this, new Dispatcher());
        _DevvitCustomPost_rootHeight.set(this, void 0);
        _DevvitCustomPost_resizeObserver.set(this, void 0);
        _DevvitCustomPost_intersectionObserver.set(this, void 0);
        _DevvitCustomPost_appVersion.set(this, '');
        _DevvitCustomPost_newRenderContext.set(this, () => ({
            experimental: this.useExperimentalBlocks,
            resolveWebviewUrl: (url) => this.disableAssetSandbox
                ? url
                : resolveWebviewUrl(this.webviewUrlTemplate, this.metadata?.[Header.Subreddit]?.values?.[0], __classPrivateFieldGet(this, _DevvitCustomPost_appVersion, "f"), url),
            onAction: (action) => __classPrivateFieldGet(this, _DevvitCustomPost_dispatcher, "f").queueRenderPost(BlockRenderEventType.RENDER_USER_ACTION, action.id, action.data ?? {}),
            stackDirection: BlockStackDirection.UNRECOGNIZED,
            disableAssetSandbox: this.disableAssetSandbox,
        }));
        _DevvitCustomPost_onError.set(this, (type, err) => {
            if (!isCircuitBreaker(err))
                console.error(err);
            __classPrivateFieldGet(this, _DevvitCustomPost_instances, "m", _DevvitCustomPost_bubble).call(this, 'devvit-ui-error', { err, type });
        });
        _DevvitCustomPost_onPluginCall.set(this, (_id, serviceName, method, args, _meta) => {
            if (serviceName === RealtimeDefinition.fullName &&
                method === RealtimeDefinition.methods.send.name) {
                if (devvit?.debug.surface || devvit?.debug.realtime)
                    console.debug('[realtime][custom] realtime plugin call', args);
                __classPrivateFieldGet(this, _DevvitCustomPost_instances, "m", _DevvitCustomPost_bubble).call(this, 'devvit-realtime-send', { event: args });
            }
        });
        _DevvitCustomPost_onRenderPost.set(this, (_, rsp) => {
            var _a, _b;
            this.renderResponse = rsp;
            if (this.renderResponse?.blocks?.ui) {
                this._rootBlock = this.renderResponse.blocks.ui;
                if (!__classPrivateFieldGet(this, _DevvitCustomPost_rootHeight, "f")) {
                    // Lock in the initial height
                    __classPrivateFieldSet(this, _DevvitCustomPost_rootHeight, this._rootBlock.config?.rootConfig?.height || DEFAULT_ROOT_HEIGHT, "f");
                }
                else {
                    (_a = this._rootBlock).config ?? (_a.config = {});
                    (_b = this._rootBlock.config).rootConfig ?? (_b.rootConfig = BlockConfig_Root.fromPartial({}));
                    this._rootBlock.config.rootConfig.height = __classPrivateFieldGet(this, _DevvitCustomPost_rootHeight, "f");
                }
            }
        });
        _DevvitCustomPost_onUserActionEffect.set(this, (fx) => {
            if (devvit?.debug.surface)
                console.debug('[custom] effect', fx);
            __classPrivateFieldGet(this, _DevvitCustomPost_instances, "m", _DevvitCustomPost_bubble).call(this, 'devvit-ui-effect', {
                effect: fx,
                onEvent: (ev) => __classPrivateFieldGet(this, _DevvitCustomPost_dispatcher, "f").queueEvent(ev),
                metadata: this.metadata,
            });
        });
        if (devvit?.debug.surface)
            console.debug('[custom] constructed');
        __classPrivateFieldGet(this, _DevvitCustomPost_dispatcher, "f").onError = __classPrivateFieldGet(this, _DevvitCustomPost_onError, "f");
        __classPrivateFieldGet(this, _DevvitCustomPost_dispatcher, "f").onPluginCall = __classPrivateFieldGet(this, _DevvitCustomPost_onPluginCall, "f");
        __classPrivateFieldGet(this, _DevvitCustomPost_dispatcher, "f").onRenderPost = __classPrivateFieldGet(this, _DevvitCustomPost_onRenderPost, "f");
        __classPrivateFieldGet(this, _DevvitCustomPost_dispatcher, "f").onUserAction = __classPrivateFieldGet(this, _DevvitCustomPost_onUserActionEffect, "f");
    }
    async connectedCallback() {
        super.connectedCallback();
        if (devvit?.debug.surface)
            console.debug('[custom] connected');
        __classPrivateFieldSet(this, _DevvitCustomPost_resizeObserver, new ResizeObserver(throttle((entries) => {
            if (entries.length === 0)
                return;
            this.dimensions = buildDimensions(entries[0], window, document.body);
            if (devvit?.debug.surface)
                console.debug('[custom] resized', this.dimensions);
        }, 600)), "f");
        __classPrivateFieldGet(this, _DevvitCustomPost_resizeObserver, "f").observe(this, { box: 'content-box' });
        __classPrivateFieldSet(this, _DevvitCustomPost_intersectionObserver, new IntersectionObserver((entries) => {
            entries.forEach((entry) => {
                if (devvit?.debug.surface)
                    console.debug(`[custom] ${entry.isIntersecting ? '' : 'not '}intersecting`);
                __classPrivateFieldGet(this, _DevvitCustomPost_dispatcher, "f").togglePause(!entry.isIntersecting);
            });
        }), "f");
        __classPrivateFieldGet(this, _DevvitCustomPost_intersectionObserver, "f").observe(this);
    }
    disconnectedCallback() {
        if (devvit?.debug.surface)
            console.debug('[custom] disconnected');
        __classPrivateFieldGet(this, _DevvitCustomPost_dispatcher, "f").unload();
        __classPrivateFieldGet(this, _DevvitCustomPost_resizeObserver, "f")?.unobserve(this);
        __classPrivateFieldGet(this, _DevvitCustomPost_intersectionObserver, "f")?.unobserve(this);
        super.disconnectedCallback();
    }
    render() {
        if (!this.renderResponse) {
            // The slot content is considered the loading state.
            return html `<slot></slot>`;
        }
        return html `<div class="relative">
      <devvit-blocks-renderer
        class="${this.scheme ?? ''}"
        .block="${this._rootBlock}"
        .renderContext="${__classPrivateFieldGet(this, _DevvitCustomPost_newRenderContext, "f")}"
      >
        <slot slot="empty-state-image" name="empty-state-image"></slot>
      </devvit-blocks-renderer>
    </div>`;
    }
    async willUpdate(props) {
        __classPrivateFieldGet(this, _DevvitCustomPost_dispatcher, "f").meta = this.metadata;
        __classPrivateFieldGet(this, _DevvitCustomPost_dispatcher, "f").postConfig = this.postConfig;
        // If the custom post has dimensions, set them on all prop updates to keep
        // the dispatcher up to date on what's happening.
        if (this.dimensions) {
            __classPrivateFieldGet(this, _DevvitCustomPost_dispatcher, "f").dimensions = this.dimensions;
        }
        if (props.has('postId')) {
            __classPrivateFieldGet(this, _DevvitCustomPost_dispatcher, "f").postID = this.postId ? asT3ID(this.postId) : undefined;
        }
        if (props.has('runtimeDebugLogging')) {
            __classPrivateFieldGet(this, _DevvitCustomPost_dispatcher, "f").runtimeDebugLogging = this.runtimeDebugLogging;
        }
        if (props.has('remoteApp')) {
            if (devvit?.debug.surface)
                console.debug(`[custom] remoteApp ${this.remoteApp ? 'defined' : 'undefined'}`);
            __classPrivateFieldGet(this, _DevvitCustomPost_dispatcher, "f").remote = this.remoteApp;
        }
        if (props.has('localRuntimeCode')) {
            if (devvit?.debug.surface)
                console.debug(`[custom] local runtime ${this.localRuntimeCode ? 'loading' : 'unloading'}`);
            __classPrivateFieldGet(this, _DevvitCustomPost_dispatcher, "f").setLocalSrc(this.localRuntimeCode);
        }
        if (props.has('bundle') && this.bundle) {
            if (devvit?.debug.surface)
                console.debug('[custom] bundle loading');
            const rsp = await __classPrivateFieldGet(this, _DevvitCustomPost_dispatcher, "f").load(this.bundle);
            if (rsp)
                __classPrivateFieldGet(this, _DevvitCustomPost_instances, "m", _DevvitCustomPost_bubble).call(this, 'devvit-loaded', rsp);
            if (devvit?.debug.surface)
                console.debug('[custom] bundle loaded');
            __classPrivateFieldSet(this, _DevvitCustomPost_appVersion, this.bundle.actor?.version ?? '', "f");
            if (props.get('bundle')) {
                if (devvit?.debug.surface || devvit?.debug.runtime)
                    console.debug('[runtime][custom] reset runtime state');
                // Bundle was _replaced_ (likely devvit-preview). Require a new render.
                this.renderResponse = undefined;
                __classPrivateFieldGet(this, _DevvitCustomPost_dispatcher, "f").resetAppState();
                __classPrivateFieldSet(this, _DevvitCustomPost_rootHeight, undefined, "f");
            }
        }
        // If the custom post does not have dimensions, block all render events until they are
        // reported. This prevents the user from being shown the jank of our custom dimensions.
        // Do not place this above the bundle loader! We want to start loading immediately
        // since it can take a few seconds.
        //
        // In case you're curious, this adds about 15ms of latency, but that pales in comparison
        // to the length of loading the local runtime.
        if (!this.dimensions)
            return;
        // We always want to trigger at least one render if:
        // 1. The app dimensions change
        // 2. The bundle changes. Loading a bundle is lengthy and dimensions may have changed during a load
        if (!__classPrivateFieldGet(this, _DevvitCustomPost_dispatcher, "f").rendered) {
            if (devvit?.debug.surface)
                console.debug('[custom] initial render');
            __classPrivateFieldGet(this, _DevvitCustomPost_dispatcher, "f").queueRenderPost(BlockRenderEventType.RENDER_INITIAL, undefined, {});
        }
        else if (props.has('dimensions') || props.has('bundle')) {
            if (devvit?.debug.surface)
                console.debug('[custom] dimensions / bundle render');
            __classPrivateFieldGet(this, _DevvitCustomPost_dispatcher, "f").queueRenderPost(BlockRenderEventType.RENDER_USER_ACTION, undefined, {});
        }
    }
};
_DevvitCustomPost_dispatcher = new WeakMap();
_DevvitCustomPost_rootHeight = new WeakMap();
_DevvitCustomPost_resizeObserver = new WeakMap();
_DevvitCustomPost_intersectionObserver = new WeakMap();
_DevvitCustomPost_appVersion = new WeakMap();
_DevvitCustomPost_newRenderContext = new WeakMap();
_DevvitCustomPost_onError = new WeakMap();
_DevvitCustomPost_onPluginCall = new WeakMap();
_DevvitCustomPost_onRenderPost = new WeakMap();
_DevvitCustomPost_onUserActionEffect = new WeakMap();
_DevvitCustomPost_instances = new WeakSet();
_DevvitCustomPost_bubble = function _DevvitCustomPost_bubble(type, detail) {
    this.dispatchEvent(customEvent(type, detail));
};
__decorate([
    property({ attribute: false }),
    __metadata("design:type", Object)
], DevvitCustomPost.prototype, "remoteApp", void 0);
__decorate([
    property({ attribute: false }),
    __metadata("design:type", Object)
], DevvitCustomPost.prototype, "bundle", void 0);
__decorate([
    property({ attribute: false }),
    __metadata("design:type", Object)
], DevvitCustomPost.prototype, "localRuntimeCode", void 0);
__decorate([
    property({ attribute: false }),
    __metadata("design:type", Object)
], DevvitCustomPost.prototype, "metadata", void 0);
__decorate([
    property({ attribute: false }),
    __metadata("design:type", Object)
], DevvitCustomPost.prototype, "postConfig", void 0);
__decorate([
    property({ attribute: 'post-id' }),
    __metadata("design:type", Object)
], DevvitCustomPost.prototype, "postId", void 0);
__decorate([
    property({ attribute: 'runtime-debug-logging', type: Boolean }),
    __metadata("design:type", Boolean)
], DevvitCustomPost.prototype, "runtimeDebugLogging", void 0);
__decorate([
    property({ attribute: 'scheme' }),
    __metadata("design:type", Object)
], DevvitCustomPost.prototype, "scheme", void 0);
__decorate([
    property({ attribute: 'use-experimental-blocks', type: Boolean }),
    __metadata("design:type", Boolean)
], DevvitCustomPost.prototype, "useExperimentalBlocks", void 0);
__decorate([
    property({ type: String }),
    __metadata("design:type", String)
], DevvitCustomPost.prototype, "webviewUrlTemplate", void 0);
__decorate([
    property({ attribute: 'disable-asset-sandbox', type: Boolean }),
    __metadata("design:type", Boolean)
], DevvitCustomPost.prototype, "disableAssetSandbox", void 0);
__decorate([
    state(),
    __metadata("design:type", Object)
], DevvitCustomPost.prototype, "renderResponse", void 0);
__decorate([
    state(),
    __metadata("design:type", Object)
], DevvitCustomPost.prototype, "dimensions", void 0);
__decorate([
    query('devvit-blocks-renderer'),
    __metadata("design:type", DevvitBlocksRenderer)
], DevvitCustomPost.prototype, "_blocksRenderer", void 0);
__decorate([
    state(),
    __metadata("design:type", Object)
], DevvitCustomPost.prototype, "_rootBlock", void 0);
DevvitCustomPost = __decorate([
    customElement('devvit-custom-post'),
    __metadata("design:paramtypes", [])
], DevvitCustomPost);
export { DevvitCustomPost };
//# sourceMappingURL=devvit-custom-post.js.map