// #region Imports
// #endregion
/**
 * Google Fonts provider that fetches fonts from the Google Fonts API.
 *
 * @public
 */
export class GoogleFontProvider {
    // #region Fields
    _options;
    _cachedFonts;
    _cachePromise;
    _loadedFonts;
    // #endregion
    // #region Ctor
    /**
     * Creates a new instance of GoogleFontProvider.
     *
     * @param options - The provider options.
     */
    constructor(options) {
        this._options = {
            cache: true,
            pageSize: 50,
            sort: 'alpha',
            ...options
        };
        this._cachedFonts = null;
        this._cachePromise = null;
        this._loadedFonts = new Map();
    }
    // #endregion
    // #region Properties
    /**
     * @inheritdoc
     */
    get name() {
        return 'google';
    }
    /**
     * @inheritdoc
     */
    get displayName() {
        return 'Google Fonts';
    }
    // #endregion
    // #region Methods
    /**
     * @inheritdoc
     */
    async fetchFonts(request) {
        const allFonts = await this.fetchAllFonts(request.signal);
        let fonts = [...allFonts];
        // Filter by search text
        if (request.searchText) {
            const searchLower = request.searchText.toLowerCase();
            fonts = fonts.filter((font) => font.family.toLowerCase().includes(searchLower));
        }
        // Filter by category
        if (request.category) {
            fonts = fonts.filter((font) => font.category === request.category);
        }
        // Filter by starting letter
        if (request.startingLetter) {
            const letter = request.startingLetter.toUpperCase();
            fonts = fonts.filter((font) => font.family.toUpperCase().startsWith(letter));
        }
        const totalCount = fonts.length;
        // Apply pagination
        if (request.pageIndex !== undefined && request.pageSize !== undefined) {
            const start = request.pageIndex * request.pageSize;
            fonts = fonts.slice(start, start + request.pageSize);
        }
        return {
            fonts,
            totalCount
        };
    }
    /**
     * @inheritdoc
     */
    loadFont(font) {
        const family = font.family;
        // Check if already loaded
        if (this._loadedFonts.has(family)) {
            return {
                dispose: () => {
                    // Don't remove if it might be used elsewhere
                }
            };
        }
        // Create link element
        const link = document.createElement('link');
        link.rel = 'stylesheet';
        link.href = `https://fonts.googleapis.com/css2?family=${encodeURIComponent(family)}:wght@100;200;300;400;500;600;700;800;900&display=swap`;
        document.head.appendChild(link);
        this._loadedFonts.set(family, link);
        return {
            dispose: () => {
                const existingLink = this._loadedFonts.get(family);
                if (existingLink) {
                    existingLink.remove();
                    this._loadedFonts.delete(family);
                }
            }
        };
    }
    /**
     * @inheritdoc
     */
    async isAvailable() {
        return Boolean(this._options.apiKey);
    }
    /**
     * Fetches all fonts from the Google Fonts API.
     *
     * @param signal - The abort signal.
     * @returns A promise that resolves to all fonts.
     */
    async fetchAllFonts(signal) {
        // Return cached results if available
        if (this._options.cache && this._cachedFonts) {
            return this._cachedFonts;
        }
        // Return existing promise if a fetch is in progress
        if (this._cachePromise) {
            return this._cachePromise;
        }
        this._cachePromise = this.doFetchFonts(signal);
        try {
            const fonts = await this._cachePromise;
            if (this._options.cache) {
                this._cachedFonts = fonts;
            }
            return fonts;
        }
        finally {
            this._cachePromise = null;
        }
    }
    /**
     * Performs the actual API fetch.
     *
     * @param signal - The abort signal.
     * @returns A promise that resolves to the fonts.
     */
    async doFetchFonts(signal) {
        const { apiKey, sort, subset } = this._options;
        let url = `https://www.googleapis.com/webfonts/v1/webfonts?key=${apiKey}&sort=${sort}`;
        if (subset) {
            url += `&subset=${subset}`;
        }
        const response = await fetch(url, { signal });
        if (!response.ok) {
            throw new Error(`Google Fonts API error: ${response.status} ${response.statusText}`);
        }
        const data = await response.json();
        return data.items.map((item) => this.mapToFont(item));
    }
    /**
     * Maps a Google Fonts API item to an IFont.
     *
     * @param item - The API item.
     * @returns The mapped font.
     */
    mapToFont(item) {
        return {
            id: `google-${item.family.toLowerCase().replace(/\s+/g, '-')}`,
            family: item.family,
            category: this.mapCategory(item.category),
            source: 'google',
            variants: item.variants,
            subsets: item.subsets,
            version: item.version,
            lastModified: item.lastModified,
            metadata: {
                files: item.files
            }
        };
    }
    /**
     * Maps a Google Fonts category to our FontCategory type.
     *
     * @param category - The Google Fonts category.
     * @returns The mapped category.
     */
    mapCategory(category) {
        const mapping = {
            'sans-serif': 'sans-serif',
            'serif': 'serif',
            'display': 'display',
            'handwriting': 'handwriting',
            'monospace': 'monospace'
        };
        return mapping[category] || 'sans-serif';
    }
}
/**
 * Creates a Google Fonts provider instance.
 *
 * @param options - The provider options.
 * @returns A new GoogleFontProvider instance.
 * @public
 */
export function createGoogleFontProvider(options) {
    return new GoogleFontProvider(options);
}
//# sourceMappingURL=GoogleFontProvider.js.map