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 __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 __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 _PlayPen_instances, _PlayPen_bundleStore, _PlayPen_env, _PlayPen_version, _PlayPen_template, _PlayPen_appendPreviewError, _PlayPen_clearPreviewErrors, _PlayPen_onShare, _PlayPen_save, _PlayPen_setName, _PlayPen_setSrc, _PlayPen_setSrcSideEffects, _PlayPen_shareURL, _PlayPen_upload;
import { throttle } from '@devvit/shared-types/throttle.js';
import { LitElement, css, html, unsafeCSS } from 'lit';
import { customElement, property, query, state } from 'lit/decorators.js';
import { ifDefined } from 'lit/directives/if-defined.js';
import { appEntrypointFilename, compile, newTSEnv, setSource } from '../../bundler/compiler.js';
import { link } from '../../bundler/linker.js';
import clock from '../../examples/clock.example.tsx';
import defaultExample from '../../examples/default.example.tsx';
import helloBlocks from '../../examples/hello-blocks.example.tsx';
import polls from '../../examples/polls.example.tsx';
import progressBar from '../../examples/progress-bar.example.tsx';
import svg from '../../examples/svg.example.tsx';
import { BundleStore } from '../../runtime/bundle-store.js';
import { PenSave, loadPen, penToHash, savePen } from '../../storage/pen-save.js';
import { defaultSettings, loadSettings, saveSettings } from '../../storage/settings-save.js';
import { newHostname } from '../../utils/compute-util.js';
import { cssReset } from '../../utils/css-reset.js';
import penVars from './pen-vars.css';
import '../play-editor/play-editor.js';
import '../play-pen-footer.js';
import '../play-pen-header.js';
import '../play-preview-controls.js';
import '../play-preview.js';
import '../play-toast.js';
/**
 * A complete and standalone playground: an editor, a runtime and client, a
 * preview and toolbar. Accepts a slotted template.
 *
 * @slot - Optional template.
 */
let PlayPen = class PlayPen extends LitElement {
    constructor() {
        super(...arguments);
        _PlayPen_instances.add(this);
        /**
         * Allow loading and saving from LocalStorage. Do not enable for multiple
         * playgrounds on the same document.
         */
        this.allowStorage = false;
        /**
         * Allow loading and saving from URL hash. Loading from hash has precedence
         * over LocalStorage. Do not enable for multiple playgrounds on the same
         * document.
         */
        this.allowURL = false;
        this.srcByLabel = {
            Default: defaultExample, // The default can be overridden by the slot.
            'Hello Blocks!': helloBlocks,
            'Progress Bar': progressBar,
            Clock: clock,
            Polls: polls,
            SVG: svg
        };
        /** Execution preview widths. */
        this._diagnostics = { previewErrs: [], tsErrs: [] };
        this._openConsole = false;
        this._previewWidth = 288;
        this._remoteRuntimeOrigin = defaultSettings.remoteRuntimeOrigin;
        this._runtimeDebugLogging = false;
        this._sandboxApp = false;
        this._useExperimentalBlocks = false;
        this._useLocalRuntime = false;
        this._useRemoteRuntime = false;
        this._useUIRequest = false;
        _PlayPen_bundleStore.set(this, void 0);
        _PlayPen_env.set(this, newTSEnv());
        this._uploaded = Promise.resolve({});
        /** Try to ensure the bundle hostname is unique. See compute-util. */
        _PlayPen_version.set(this, Date.now()
        /** Program title. */ );
        /** Program title. */ this._name = '';
        _PlayPen_template.set(this, void 0);
        /** Throttled changes after updating sources. */
        _PlayPen_setSrcSideEffects.set(this, throttle((save) => {
            var _a;
            __classPrivateFieldSet(this, _PlayPen_version, (_a = __classPrivateFieldGet(this, _PlayPen_version, "f"), _a++, _a), "f");
            this._bundle = link(compile(__classPrivateFieldGet(this, _PlayPen_env, "f")), newHostname(this._name, __classPrivateFieldGet(this, _PlayPen_version, "f")));
            if (save)
                __classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_save).call(this);
            __classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_upload).call(this);
        }, 500)
        /** Recompute the current hash regardless of the location bar state. */
        );
    }
    connectedCallback() {
        super.connectedCallback();
        const settings = (this.allowStorage ? loadSettings(localStorage) : undefined) ??
            defaultSettings;
        if (settings) {
            this._openConsole = settings.openConsole;
            this._remoteRuntimeOrigin = settings.remoteRuntimeOrigin;
            this._runtimeDebugLogging = settings.runtimeDebugLogging;
            this._sandboxApp = settings.sandboxApp;
            this._useExperimentalBlocks = settings.useExperimentalBlocks;
            this._useLocalRuntime = settings.useLocalRuntime;
            this._useRemoteRuntime = settings.useRemoteRuntime;
            this._useUIRequest = settings.useUIRequest;
            // If remote is enabled, #bundleStore is initialized in willUpdate() and
            // bundle is loaded.
        }
        let pen;
        if (this.allowURL)
            pen = loadPen(location);
        if (this.allowStorage)
            pen ?? (pen = loadPen(localStorage));
        if (!pen) {
            __classPrivateFieldSet(this, _PlayPen_template, true, "f");
            __classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_setSrc).call(this, helloBlocks, false);
            return;
        }
        __classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_setSrc).call(this, pen.src, false);
        __classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_setName).call(this, pen.name, false);
    }
    render() {
        return html `
      <play-toast>Copied the URL!</play-toast
      ><play-pen-header
        ?allow-storage=${this.allowStorage}
        name=${this._name}
        remote-runtime-origin=${this._remoteRuntimeOrigin}
        ?runtime-debug-logging=${this._runtimeDebugLogging}
        ?sandbox-app=${this._sandboxApp}
        .srcByLabel=${this.srcByLabel}
        url=${__classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_shareURL).call(this).toString()}
        ?use-experimental-blocks=${this._useExperimentalBlocks}
        ?use-local-runtime=${this._useLocalRuntime}
        ?use-remote-runtime=${this._useRemoteRuntime}
        ?use-ui-request=${this._useUIRequest}
        @edit-name=${(ev) => __classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_setName).call(this, ev.detail, true)}
        @edit-src=${(ev) => {
            __classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_setSrc).call(this, ev.detail, false);
            __classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_setName).call(this, '', false);
            this._editor.setSrc(ev.detail);
        }}
        @runtime-debug-logging=${(ev) => (this._runtimeDebugLogging = ev.detail)}
        @sandbox-app=${(ev) => (this._sandboxApp = ev.detail)}
        @use-experimental-blocks=${(ev) => (this._useExperimentalBlocks = ev.detail)}
        @use-local-runtime=${(ev) => (this._useLocalRuntime = ev.detail)}
        @use-remote-runtime=${(ev) => (this._useRemoteRuntime = ev.detail)}
        @edit-remote-runtime-origin=${(ev) => (this._remoteRuntimeOrigin = ev.detail)}
        @use-ui-request=${(ev) => (this._useUIRequest = ev.detail)}
        @share=${__classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_onShare)}
      ></play-pen-header>
      <main>
        <play-editor
          .env=${__classPrivateFieldGet(this, _PlayPen_env, "f")}
          src=${ifDefined(this._src)}
          @edit=${(ev) => __classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_setSrc).call(this, ev.detail, true)}
          @edit-template=${(ev) => {
            this.srcByLabel = { ...this.srcByLabel, ['Default']: ev.detail };
            if (!__classPrivateFieldGet(this, _PlayPen_template, "f"))
                return;
            // If no source was restored, use the template.
            __classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_setSrc).call(this, ev.detail, false);
            this._editor.setSrc(ev.detail);
        }}
          ><slot></slot
        ></play-editor>
        <div class="preview">
          <play-preview
            .bundle=${this._bundle}
            previewWidth=${this._previewWidth}
            remote-runtime-origin=${this._remoteRuntimeOrigin}
            ?runtime-debug-logging=${this._runtimeDebugLogging}
            ?sandbox-app=${this._sandboxApp}
            scheme=${ifDefined(this._scheme)}
            .uploaded=${this._uploaded}
            ?use-experimental-blocks=${this._useExperimentalBlocks}
            ?use-local-runtime=${this._useLocalRuntime}
            ?use-remote-runtime=${this._useRemoteRuntime}
            ?use-ui-request=${this._useUIRequest}
            @clear-errors=${() => __classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_clearPreviewErrors).call(this)}
            @devvit-ui-error=${(ev) => __classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_appendPreviewError).call(this, ev.detail)}
          ></play-preview>
          <play-preview-controls
            previewWidth=${this._previewWidth}
            scheme=${ifDefined(this._scheme)}
            @preview-reset=${() => {
            if (this._bundle)
                this._bundle = { ...this._bundle };
        }}
            @preview-width=${(ev) => (this._previewWidth = ev.detail)}
            @preview-scheme=${(ev) => (this._scheme = ev.detail)}
          ></play-preview-controls>
        </div>
      </main>
      <play-pen-footer
        .diagnostics=${this._diagnostics}
        ?open-console=${this._openConsole}
        @open-console=${(ev) => (this._openConsole = ev.detail)}
        @preview-width=${(ev) => (this._previewWidth = ev.detail)}
        @preview-scheme=${(ev) => (this._scheme = ev.detail)}
        @open-line=${(ev) => this._editor.openLine(ev.detail.line, ev.detail.char)}
      ></play-pen-footer>
    `;
    }
    async willUpdate(props) {
        super.willUpdate(props);
        if (this.allowStorage &&
            (props.has('_openConsole') ||
                props.has('_runtimeDebugLogging') ||
                props.has('_sandboxApp') ||
                props.has('_useExperimentalBlocks') ||
                props.has('_remoteRuntimeOrigin') ||
                props.has('_useLocalRuntime') ||
                props.has('_useRemoteRuntime') ||
                props.has('_useUIRequest')))
            saveSettings(localStorage, {
                openConsole: this._openConsole,
                runtimeDebugLogging: this._runtimeDebugLogging,
                sandboxApp: this._sandboxApp,
                useExperimentalBlocks: this._useExperimentalBlocks,
                useLocalRuntime: this._useLocalRuntime,
                useRemoteRuntime: this._useRemoteRuntime,
                remoteRuntimeOrigin: this._remoteRuntimeOrigin,
                useUIRequest: this._useUIRequest,
                version: 1
            });
        if (props.has('_remoteRuntimeOrigin'))
            __classPrivateFieldSet(this, _PlayPen_bundleStore, BundleStore(this._remoteRuntimeOrigin), "f");
        if (props.has('_useRemoteRuntime') || props.has('_remoteRuntimeOrigin'))
            __classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_upload).call(this);
    }
};
_PlayPen_bundleStore = new WeakMap();
_PlayPen_env = new WeakMap();
_PlayPen_version = new WeakMap();
_PlayPen_template = new WeakMap();
_PlayPen_setSrcSideEffects = new WeakMap();
_PlayPen_instances = new WeakSet();
_PlayPen_appendPreviewError = function _PlayPen_appendPreviewError(err) {
    this._diagnostics = {
        ...this._diagnostics,
        previewErrs: [...this._diagnostics.previewErrs, err]
    };
};
_PlayPen_clearPreviewErrors = function _PlayPen_clearPreviewErrors() {
    if (this._diagnostics)
        this._diagnostics.previewErrs.length = 0;
    this._diagnostics = { ...this._diagnostics };
};
_PlayPen_onShare = async function _PlayPen_onShare() {
    await navigator.clipboard.writeText(__classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_shareURL).call(this).toString());
    this._toast.open();
};
_PlayPen_save = function _PlayPen_save() {
    savePen(this.allowURL ? location : undefined, this.allowStorage ? localStorage : undefined, PenSave(this._name, this._src ?? ''));
};
_PlayPen_setName = function _PlayPen_setName(name, save) {
    this._name = name;
    if (save)
        __classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_save).call(this);
};
_PlayPen_setSrc = function _PlayPen_setSrc(src, save) {
    this._src = src;
    setSource(__classPrivateFieldGet(this, _PlayPen_env, "f"), src);
    __classPrivateFieldGet(this, _PlayPen_env, "f").updateFile(appEntrypointFilename, src || ' '); // empty strings trigger file deletion!
    this._diagnostics = {
        ...this._diagnostics,
        tsErrs: __classPrivateFieldGet(this, _PlayPen_env, "f").languageService.getSemanticDiagnostics(appEntrypointFilename)
    };
    __classPrivateFieldGet(this, _PlayPen_setSrcSideEffects, "f").call(this, save);
};
_PlayPen_shareURL = function _PlayPen_shareURL() {
    const url = new URL(location.toString());
    url.hash = penToHash(PenSave(this._name, this._src ?? ''));
    return url;
};
_PlayPen_upload = function _PlayPen_upload() {
    // Unlike production, bundles are first available locally and then remotely.
    // Upload failures appear in the execution of RemoteApp.
    if (this._useRemoteRuntime && this._bundle)
        this._uploaded =
            __classPrivateFieldGet(this, _PlayPen_bundleStore, "f")?.upload(this._bundle) ?? Promise.resolve({});
};
PlayPen.styles = css `
    ${cssReset}

    ${unsafeCSS(penVars)}

    :host {
      /* Light mode. */
      color: var(--color-foreground);
      background-color: var(--color-background);

      width: 100%;
      height: 100%;
      display: flex;
      flex-direction: column;

      /* Dark and light schemes are supported. */
      color-scheme: dark light;
    }

    play-editor {
      width: 100%;
      flex-grow: 1;
      flex-shrink: 1;
    }

    .preview {
      flex-shrink: 0;
      display: flex;
      flex-direction: column;
      row-gap: 8px;
    }

    main {
      column-gap: 16px;
      display: flex;
      flex-direction: row;
      overflow: clip;
      padding-right: 16px;
      padding-left: 16px;
      row-gap: 16px;
      height: 100%;
      background-color: var(--color-background);
      z-index: var(--z-base);
    }

    /* Makes dropdowns appear over other content */
    play-pen-header,
    play-pen-footer {
      z-index: var(--z-menu);
    }
  `;
__decorate([
    property({ attribute: 'allow-storage', type: Boolean })
], PlayPen.prototype, "allowStorage", void 0);
__decorate([
    property({ attribute: 'allow-url', type: Boolean })
], PlayPen.prototype, "allowURL", void 0);
__decorate([
    property({ attribute: false })
], PlayPen.prototype, "srcByLabel", void 0);
__decorate([
    state()
], PlayPen.prototype, "_bundle", void 0);
__decorate([
    state()
], PlayPen.prototype, "_diagnostics", void 0);
__decorate([
    state()
], PlayPen.prototype, "_openConsole", void 0);
__decorate([
    state()
], PlayPen.prototype, "_previewWidth", void 0);
__decorate([
    state()
], PlayPen.prototype, "_remoteRuntimeOrigin", void 0);
__decorate([
    state()
], PlayPen.prototype, "_runtimeDebugLogging", void 0);
__decorate([
    state()
], PlayPen.prototype, "_sandboxApp", void 0);
__decorate([
    state()
], PlayPen.prototype, "_useExperimentalBlocks", void 0);
__decorate([
    state()
], PlayPen.prototype, "_useLocalRuntime", void 0);
__decorate([
    state()
], PlayPen.prototype, "_useRemoteRuntime", void 0);
__decorate([
    state()
], PlayPen.prototype, "_useUIRequest", void 0);
__decorate([
    query('play-editor')
], PlayPen.prototype, "_editor", void 0);
__decorate([
    query('play-toast')
], PlayPen.prototype, "_toast", void 0);
__decorate([
    state()
], PlayPen.prototype, "_uploaded", void 0);
__decorate([
    state()
], PlayPen.prototype, "_name", void 0);
__decorate([
    state()
], PlayPen.prototype, "_scheme", void 0);
__decorate([
    state()
], PlayPen.prototype, "_src", void 0);
PlayPen = __decorate([
    customElement('play-pen')
], PlayPen);
export { PlayPen };
//# sourceMappingURL=play-pen.js.map