import * as i0 from '@angular/core';
import { Injectable, inject, DestroyRef, input, signal, Component } from '@angular/core';
import { C as ContentBuilderStore, a as CONTENT_BUILDER } from './ngstarter-ui-components-content-editor-ngstarter-ui-components-content-editor-DNLTNGYa.mjs';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { Icon } from '@ngstarter-ui/components/icon';
import { Popover, PopoverTriggerForDirective } from '@ngstarter-ui/components/popover';
import { TabGroup, Tab } from '@ngstarter-ui/components/tabs';
import { Button } from '@ngstarter-ui/components/button';
import { Input } from '@ngstarter-ui/components/input';
import { FormField, Suffix } from '@ngstarter-ui/components/form-field';
import * as i1 from '@angular/forms';
import { FormBuilder, Validators, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { SafeResourceUrlPipe } from '@ngstarter-ui/components/core';

class EmbedService {
    parse(rawUrl) {
        const cleaned = (rawUrl || '').trim();
        if (!cleaned) {
            return { url: '', type: '' };
        }
        const withScheme = /^(https?:)?\/\//i.test(cleaned) ? cleaned : `https://${cleaned}`;
        let u = null;
        try {
            u = new URL(withScheme);
        }
        catch {
            return { url: cleaned, type: '' };
        }
        const host = u.hostname.toLowerCase();
        const path = u.pathname.toLowerCase();
        const href = u.toString();
        if (path.endsWith('.pdf')) {
            return { url: href, type: 'pdf' };
        }
        else if (host.includes('youtu.be') || host.includes('youtube.com')) {
            return { url: this.toYoutubeEmbed(u), type: 'youtube' };
        }
        else if (host.includes('vimeo.com')) {
            return { url: this.toVimeoEmbed(u), type: 'vimeo' };
        }
        else if (host.includes('spotify.com')) {
            return { url: this.toSpotifyEmbed(u), type: 'spotify' };
        }
        else if (host.includes('maps.google.') || (host.includes('google.') && path.startsWith('/maps'))) {
            return { url: this.toGoogleMapsEmbed(u), type: 'google-maps' };
        }
        else if (host.includes('docs.google.')) {
            return { url: this.toGoogleDocsEmbed(u), type: 'google-docs' };
        }
        else if (host.includes('drive.google.')) {
            return { url: this.toGoogleDriveEmbed(u), type: 'google-drive' };
        }
        else if (host.includes('codepen.io')) {
            return { url: this.toCodepenEmbed(u), type: 'codepen' };
        }
        else if (host.includes('figma.com')) {
            return { url: this.toFigmaEmbed(u), type: 'figma' };
        }
        else if (host.includes('loom.com')) {
            return { url: this.toLoomEmbed(u), type: 'loom' };
        }
        else if (host.includes('twitter.com') || host === 'x.com' || host.endsWith('.x.com')) {
            return { url: this.toTwitterEmbed(u), type: 'twitter' };
        }
        else if (host.includes('instagram.com')) {
            return { url: this.toInstagramEmbed(u), type: 'instagram' };
        }
        else if (host.includes('tiktok.com')) {
            return { url: this.toTiktokEmbed(u), type: 'tiktok' };
        }
        else if (host.includes('soundcloud.com')) {
            return { url: this.toSoundcloudEmbed(u), type: 'soundcloud' };
        }
        else if (host.includes('stackblitz.com')) {
            return { url: this.toStackblitzEmbed(u), type: 'stackblitz' };
        }
        else if (host.includes('gist.github.com')) {
            return { url: href, type: 'gist' };
        }
        else {
            return { url: href, type: 'website' };
        }
    }
    // ==== Provider transformers ====
    toYoutubeEmbed(u) {
        // Already embed
        if (/^\/embed\//.test(u.pathname)) {
            return `https://www.youtube.com${u.pathname}${u.search}`;
        }
        const host = u.hostname.toLowerCase();
        let id = '';
        let start = '';
        if (host.includes('youtu.be')) {
            id = u.pathname.split('/').filter(Boolean)[0] || '';
            // t or start
            start = this.extractYouTubeStart(u.searchParams);
        }
        else {
            // youtube.com variants
            if (u.searchParams.get('v')) {
                id = u.searchParams.get('v') || '';
                start = this.extractYouTubeStart(u.searchParams);
            }
            else if (u.pathname.startsWith('/shorts/')) {
                id = u.pathname.split('/')[2] || '';
            }
            else if (u.pathname.startsWith('/live/')) {
                id = u.pathname.split('/')[2] || '';
            }
        }
        const qs = start ? `?start=${start}` : '';
        return id ? `https://www.youtube.com/embed/${id}${qs}` : u.toString();
    }
    extractYouTubeStart(params) {
        const t = params.get('t') || params.get('start') || '';
        if (!t)
            return '';
        // t can be in format 1h2m3s or 90 or 1m30s
        const total = this.parseTimeToSeconds(t);
        return total ? String(total) : '';
    }
    parseTimeToSeconds(t) {
        if (/^\d+$/.test(t))
            return parseInt(t, 10);
        const re = /(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?/i;
        const m = t.match(re);
        if (!m)
            return 0;
        const h = parseInt(m[1] || '0', 10);
        const mnt = parseInt(m[2] || '0', 10);
        const s = parseInt(m[3] || '0', 10);
        return h * 3600 + mnt * 60 + s;
    }
    toVimeoEmbed(u) {
        // extract last numeric id
        const parts = u.pathname.split('/').filter(Boolean);
        const last = parts[parts.length - 1] || '';
        const id = /^(\d+)$/.test(last) ? last : (parts.includes('videos') ? parts[parts.indexOf('videos') + 1] : '');
        return id ? `https://player.vimeo.com/video/${id}` : u.toString();
    }
    toSpotifyEmbed(u) {
        const parts = u.pathname.split('/').filter(Boolean);
        if (parts[0] === 'embed')
            return u.toString();
        // /{type}/{id}
        if (parts.length >= 2) {
            const type = parts[0];
            const id = parts[1];
            return `https://open.spotify.com/embed/${type}/${id}`;
        }
        return u.toString();
    }
    toGoogleMapsEmbed(u) {
        const p = u.pathname;
        if (p.includes('/maps/embed') || u.searchParams.get('output') === 'embed') {
            return u.toString();
        }
        // Best-effort wrap original URL as query for embed
        return `https://www.google.com/maps?output=embed&q=${encodeURIComponent(u.toString())}`;
    }
    toGoogleDocsEmbed(u) {
        // document, presentation, spreadsheets, forms
        const parts = u.pathname.split('/').filter(Boolean);
        if (parts.length >= 3) {
            const product = parts[0]; // document|presentation|spreadsheets|forms
            const kind = parts[1]; // usually 'd'
            const id = parts[2];
            if (product === 'document') {
                return `https://docs.google.com/document/d/${id}/preview`;
            }
            if (product === 'presentation') {
                return `https://docs.google.com/presentation/d/${id}/embed`;
            }
            if (product === 'spreadsheets') {
                return `https://docs.google.com/spreadsheets/d/${id}/preview`;
            }
            if (product === 'forms') {
                return `https://docs.google.com/forms/d/${id}/viewform?embedded=true`;
            }
        }
        return u.toString();
    }
    toGoogleDriveEmbed(u) {
        // /file/d/{id}/view -> /file/d/{id}/preview
        const parts = u.pathname.split('/').filter(Boolean);
        const idx = parts.indexOf('d');
        if (parts[0] === 'file' && idx >= 0 && parts[idx + 1]) {
            const id = parts[idx + 1];
            return `https://drive.google.com/file/d/${id}/preview`;
        }
        // open?id=... -> uc?export=preview&id=...
        const openId = u.searchParams.get('id');
        if (openId) {
            return `https://drive.google.com/uc?export=preview&id=${encodeURIComponent(openId)}`;
        }
        return u.toString();
    }
    toCodepenEmbed(u) {
        const parts = u.pathname.split('/').filter(Boolean);
        const user = parts[0];
        const mode = parts[1]; // pen|full|details|embed
        const id = parts[2];
        if (mode === 'embed')
            return u.toString();
        if (user && id) {
            return `https://codepen.io/${user}/embed/${id}`;
        }
        return u.toString();
    }
    toFigmaEmbed(u) {
        return `https://www.figma.com/embed?embed_host=share&url=${encodeURIComponent(u.toString())}`;
    }
    toLoomEmbed(u) {
        const parts = u.pathname.split('/').filter(Boolean);
        if (parts[0] === 'embed')
            return u.toString();
        // /share/{id}
        if (parts[0] === 'share' && parts[1]) {
            return `https://www.loom.com/embed/${parts[1]}`;
        }
        return u.toString();
    }
    toTwitterEmbed(u) {
        // Use twitframe to get an embeddable iframe
        return `https://twitframe.com/show?url=${encodeURIComponent(u.toString())}`;
    }
    toInstagramEmbed(u) {
        // Append /embed to post/reel URLs
        let p = u.pathname;
        if (!p.endsWith('/'))
            p += '/';
        if (!p.endsWith('embed/')) {
            p += 'embed/';
        }
        return `${u.protocol}//${u.host}${p}`;
    }
    toTiktokEmbed(u) {
        // Expect /@user/video/{id}
        const parts = u.pathname.split('/').filter(Boolean);
        const idx = parts.indexOf('video');
        if (idx >= 0 && parts[idx + 1]) {
            const id = parts[idx + 1];
            return `https://www.tiktok.com/embed/v2/${id}`;
        }
        return u.toString();
    }
    toSoundcloudEmbed(u) {
        return `https://w.soundcloud.com/player/?url=${encodeURIComponent(u.toString())}`;
    }
    toStackblitzEmbed(u) {
        // Ensure we have the embed parameter for StackBlitz iframe
        const url = new URL(u.toString());
        if (url.searchParams.get('embed') !== '1') {
            url.searchParams.set('embed', '1');
        }
        // Keep other parameters like file, terminal, ctl, hideExplorer if provided by user
        return url.toString();
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: EmbedService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: EmbedService });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: EmbedService, decorators: [{
            type: Injectable
        }] });

class EmbedBlock {
    store = inject(ContentBuilderStore);
    contentBuilder = inject(CONTENT_BUILDER);
    destroyRef = inject(DestroyRef);
    formBuilder = inject(FormBuilder);
    embedService = inject(EmbedService);
    id = input.required(...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
    content = input.required(...(ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []));
    settings = input.required(...(ngDevMode ? [{ debugName: "settings" }] : /* istanbul ignore next */ []));
    props = input([], ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
    index = input.required(...(ngDevMode ? [{ debugName: "index" }] : /* istanbul ignore next */ []));
    embedUrlValidator = (control) => {
        const value = (control.value ?? '').toString();
        if (!value.trim()) {
            return null;
        }
        const { type } = this.embedService.parse(value);
        if (!type || type === 'website') {
            return { embedUrl: true };
        }
        return null;
    };
    form = this.formBuilder.nonNullable.group({
        url: ['', [Validators.required, this.embedUrlValidator]],
    });
    _content = signal({
        url: '',
        type: ''
    }, ...(ngDevMode ? [{ debugName: "_content" }] : /* istanbul ignore next */ []));
    _settings = signal({
        width: null,
        height: null
    }, ...(ngDevMode ? [{ debugName: "_settings" }] : /* istanbul ignore next */ []));
    _props = signal([], ...(ngDevMode ? [{ debugName: "_props" }] : /* istanbul ignore next */ []));
    initialized = signal(false, ...(ngDevMode ? [{ debugName: "initialized" }] : /* istanbul ignore next */ []));
    ngOnInit() {
        this._content.set(this.content());
        this._settings.set(this.settings());
        this._props.set(this.props());
        this.contentBuilder
            .focusChanged
            .pipe(takeUntilDestroyed(this.destroyRef))
            .subscribe(() => {
            if (this.store.focusedBlockId() === this.id()) {
            }
        });
    }
    getData() {
        return {
            content: this._content(),
            props: this._props(),
            settings: this._settings()
        };
    }
    isEmpty() {
        return this.getData().content.url === '' && this.getData().content.type === '';
    }
    embed(trigger) {
        this._content.set(this.embedService.parse(this.form.value.url || ''));
        trigger.api.close();
        this.store.updateBlock(this.id(), { ...this.getData(), isEmpty: this.isEmpty() });
        this.contentBuilder.emitContentChangeEvent();
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: EmbedBlock, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: EmbedBlock, isStandalone: true, selector: "app-embed-block", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: true, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: true, transformFunction: null }, settings: { classPropertyName: "settings", publicName: "settings", isSignal: true, isRequired: true, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, index: { classPropertyName: "index", publicName: "index", isSignal: true, isRequired: true, transformFunction: null } }, host: { properties: { "class.is-empty": "isEmpty()" }, classAttribute: "ngs-embed-block" }, providers: [EmbedService], ngImport: i0, template: "@if (isEmpty()) {\n  <div class=\"bg-surface-container-low cursor-pointer hover:bg-surface-container p-4 rounded-2xl flex items-center gap-3\"\n       #trigger=\"ngsPopoverTriggerFor\"\n       [ngsPopoverTriggerFor]=\"addPopover\" position=\"below-center\" trigger=\"click\" hasBackdrop>\n    <ngs-icon name=\"fluent:globe-24-regular\"/>\n    <div class=\"text-sm\">Embed anything (PDFs, Google Docs, Google Maps, Spotify\u2026)</div>\n  </div>\n  <ngs-popover #addPopover>\n    <div class=\"w-[400px] overflow-hidden\">\n      <ngs-tab-group>\n        <ngs-tab label=\"Embed\">\n          <div class=\"p-4\">\n            <ngs-form-field class=\"w-full\">\n              <input ngsInput [formControl]=\"form.controls.url\" placeholder=\"Paste in https://...\">\n              <div ngsSuffix class=\"pe-2\">\n                <button ngsButton=\"filled\" type=\"button\" [disabled]=\"form.invalid\" (click)=\"embed(trigger)\">Embed</button>\n              </div>\n            </ngs-form-field>\n            <p class=\"text-xs text-center\">Works with links of PDFs, Google Drive, Google Maps, CodePen\u2026</p>\n          </div>\n        </ngs-tab>\n        <ngs-tab label=\"Upload\">\n          <div class=\"p-4\">\n            <div>\n              <button ngsButton=\"filled\" class=\"w-full\">Upload</button>\n            </div>\n            <p class=\"text-xs text-center mt-4\">Upload a file from your computer.</p>\n          </div>\n        </ngs-tab>\n      </ngs-tab-group>\n    </div>\n  </ngs-popover>\n} @else {\n  <div class=\"w-full bg-surface-container-low w-[700px] h-[400px]\">\n    <iframe width=\"100%\" height=\"100%\" [src]=\"_content().url | safeResourceUrl\" frameborder=\"0\" allowfullscreen></iframe>\n  </div>\n}\n", styles: [""], dependencies: [{ kind: "component", type: Icon, selector: "ngs-icon", inputs: ["name"], exportAs: ["ngsIcon"] }, { kind: "component", type: Popover, selector: "ngs-popover", exportAs: ["ngsPopover"] }, { kind: "directive", type: PopoverTriggerForDirective, selector: "[ngsPopoverTriggerFor]", inputs: ["ngsPopoverTriggerFor", "ngsPopoverContext", "trigger", "position", "delay", "origin", "closeOnOriginClick", "closeOnOriginMouseLeave", "hasBackdrop"], outputs: ["opened", "closed"], exportAs: ["ngsPopoverTriggerFor"] }, { kind: "component", type: TabGroup, selector: "ngs-tab-group", inputs: ["selectedIndex", "headerPosition", "preserveContent", "ngs-stretch-tabs", "ngs-align-tabs", "disableRipple", "animationDuration", "animate.enter", "animate.leave"], outputs: ["selectedIndexChange", "selectedTabChange", "focusChange"] }, { kind: "component", type: Tab, selector: "ngs-tab", inputs: ["label", "aria-label", "aria-labelledby", "disabled"], exportAs: ["ngsTab"] }, { kind: "component", type: Button, selector: "    button[ngsButton], button[ngsIconButton],    a[ngsButton], a[ngsIconButton]  ", inputs: ["ngsButton", "ngsIconButton", "loading", "disabled", "disabledInteractive", "disableRipple", "reverse", "fullWidth", "hideTextOnMobile"], exportAs: ["ngsButton"] }, { kind: "component", type: FormField, selector: "ngs-form-field", inputs: ["subscriptHiddenIfEmpty"], exportAs: ["ngsFormField"] }, { kind: "directive", type: Input, selector: "input[ngsInput], textarea[ngsInput]", inputs: ["id", "placeholder", "required", "disabled", "readonly", "errorStateMatcher"], exportAs: ["ngsInput"] }, { kind: "directive", type: Suffix, selector: "[ngsSuffix]" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "pipe", type: SafeResourceUrlPipe, name: "safeResourceUrl" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: EmbedBlock, decorators: [{
            type: Component,
            args: [{ selector: 'app-embed-block', imports: [
                        Icon,
                        Popover,
                        PopoverTriggerForDirective,
                        TabGroup,
                        Tab,
                        Button,
                        FormField,
                        Input,
                        Suffix,
                        FormsModule,
                        ReactiveFormsModule,
                        SafeResourceUrlPipe
                    ], providers: [EmbedService], host: {
                        'class': 'ngs-embed-block',
                        '[class.is-empty]': 'isEmpty()'
                    }, template: "@if (isEmpty()) {\n  <div class=\"bg-surface-container-low cursor-pointer hover:bg-surface-container p-4 rounded-2xl flex items-center gap-3\"\n       #trigger=\"ngsPopoverTriggerFor\"\n       [ngsPopoverTriggerFor]=\"addPopover\" position=\"below-center\" trigger=\"click\" hasBackdrop>\n    <ngs-icon name=\"fluent:globe-24-regular\"/>\n    <div class=\"text-sm\">Embed anything (PDFs, Google Docs, Google Maps, Spotify\u2026)</div>\n  </div>\n  <ngs-popover #addPopover>\n    <div class=\"w-[400px] overflow-hidden\">\n      <ngs-tab-group>\n        <ngs-tab label=\"Embed\">\n          <div class=\"p-4\">\n            <ngs-form-field class=\"w-full\">\n              <input ngsInput [formControl]=\"form.controls.url\" placeholder=\"Paste in https://...\">\n              <div ngsSuffix class=\"pe-2\">\n                <button ngsButton=\"filled\" type=\"button\" [disabled]=\"form.invalid\" (click)=\"embed(trigger)\">Embed</button>\n              </div>\n            </ngs-form-field>\n            <p class=\"text-xs text-center\">Works with links of PDFs, Google Drive, Google Maps, CodePen\u2026</p>\n          </div>\n        </ngs-tab>\n        <ngs-tab label=\"Upload\">\n          <div class=\"p-4\">\n            <div>\n              <button ngsButton=\"filled\" class=\"w-full\">Upload</button>\n            </div>\n            <p class=\"text-xs text-center mt-4\">Upload a file from your computer.</p>\n          </div>\n        </ngs-tab>\n      </ngs-tab-group>\n    </div>\n  </ngs-popover>\n} @else {\n  <div class=\"w-full bg-surface-container-low w-[700px] h-[400px]\">\n    <iframe width=\"100%\" height=\"100%\" [src]=\"_content().url | safeResourceUrl\" frameborder=\"0\" allowfullscreen></iframe>\n  </div>\n}\n" }]
        }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: true }] }], settings: [{ type: i0.Input, args: [{ isSignal: true, alias: "settings", required: true }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], index: [{ type: i0.Input, args: [{ isSignal: true, alias: "index", required: true }] }] } });

export { EmbedBlock };
//# sourceMappingURL=ngstarter-ui-components-content-editor-embed-block-ghm0_0AF.mjs.map
