import * as i0 from '@angular/core';
import { Injectable, NgModule, Optional } from '@angular/core';
import * as i1 from '@angular-ru/cdk/webworker';
import { WebWorkerThreadService } from '@angular-ru/cdk/webworker';
import { copyHtml, isNotNil } from '@angular-ru/cdk/utils';
import * as i3 from '@ngx-translate/core';
import { of, firstValueFrom } from 'rxjs';

// eslint-disable-next-line max-classes-per-file
class PlainTableComposerService {
    constructor(webWorker) {
        this.webWorker = webWorker;
    }
    async composeSingle(entry, keyRules) {
        const [composed] = await this.compose([entry], keyRules);
        return composed ?? {};
    }
    // eslint-disable-next-line max-lines-per-function
    compose(tableEntries, keyRules) {
        return (this.webWorker
            // eslint-disable-next-line max-lines-per-function,sonarjs/cognitive-complexity
            .run(
        // eslint-disable-next-line sonarjs/cognitive-complexity,max-lines-per-function
        (input) => {
            class PlainComposer {
                constructor(rules) {
                    this.rules = rules;
                    this.keySet = new Set();
                }
                static isObject(value) {
                    return typeof value === 'object' && value !== null;
                }
                toPlain(rawEntries) {
                    this.keySet.clear();
                    const flatEntries = rawEntries.map((entry) => this.flattenAndClean(entry));
                    const keys = this.rules?.includeKeys ?? Array.from(this.keySet);
                    return flatEntries.map((entry) => this.pickKeys(entry, keys));
                }
                flattenAndClean(objectRef, keyPrefix = '') {
                    const depthGraph = {};
                    const keys = Object.keys(objectRef);
                    for (const key of keys) {
                        const path = keyPrefix ? `${keyPrefix}.${key}` : key;
                        if (this.passesBlacklist(path)) {
                            if (PlainComposer.isObject(objectRef[key])) {
                                const childKeys = this.flattenAndClean(objectRef[key], path);
                                Object.assign(depthGraph, childKeys);
                            }
                            else {
                                this.keySet.add(path);
                                depthGraph[path] = objectRef[key];
                            }
                        }
                    }
                    return depthGraph;
                }
                pickKeys(source, keys) {
                    return keys.reduce((collected, key) => {
                        collected[key] = source[key];
                        return collected;
                    }, {});
                }
                passesBlacklist(key) {
                    if (this.rules?.excludeKeys) {
                        return !this.rules.excludeKeys.includes(key);
                    }
                    else {
                        return true;
                    }
                }
            }
            return new PlainComposer(input.rules).toPlain(input.entries);
        }, { rules: keyRules, entries: tableEntries }));
    }
}
/** @nocollapse */ PlainTableComposerService.ɵfac = function PlainTableComposerService_Factory(t) { return new (t || PlainTableComposerService)(i0.ɵɵinject(i1.WebWorkerThreadService)); };
/** @nocollapse */ PlainTableComposerService.ɵprov = /** @pureOrBreakMyCode */ i0.ɵɵdefineInjectable({ token: PlainTableComposerService, factory: PlainTableComposerService.ɵfac });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PlainTableComposerService, [{
        type: Injectable
    }], function () { return [{ type: i1.WebWorkerThreadService }]; }, null); })();

class PlainTableComposerModule {
    static forRoot() {
        return {
            ngModule: PlainTableComposerModule,
            providers: [PlainTableComposerService]
        };
    }
}
/** @nocollapse */ PlainTableComposerModule.ɵfac = function PlainTableComposerModule_Factory(t) { return new (t || PlainTableComposerModule)(); };
/** @nocollapse */ PlainTableComposerModule.ɵmod = /** @pureOrBreakMyCode */ i0.ɵɵdefineNgModule({ type: PlainTableComposerModule });
/** @nocollapse */ PlainTableComposerModule.ɵinj = /** @pureOrBreakMyCode */ i0.ɵɵdefineInjector({ providers: [WebWorkerThreadService] });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PlainTableComposerModule, [{
        type: NgModule,
        args: [{
                providers: [WebWorkerThreadService]
            }]
    }], null, null); })();

/* eslint-disable unicorn/consistent-function-scoping */
class TableClipboardService {
    constructor(plainTableComposer, webWorker, translate) {
        this.plainTableComposer = plainTableComposer;
        this.webWorker = webWorker;
        this.translate = translate;
    }
    // eslint-disable-next-line max-lines-per-function
    async generateTableAndCopy(request) {
        const preparedRequest = {
            ...request,
            entries: await this.plainTableComposer.compose(request.entries, request.rules),
            translationMap: request.translationMap ?? (await this.getTranslationMap())
        };
        return (this.webWorker
            // eslint-disable-next-line max-lines-per-function
            .run((input) => {
            function isEmptyValue(value) {
                const nextValue = typeof value === 'string' ? value.trim() : value;
                return [undefined, null, NaN, '', Infinity].includes(nextValue);
            }
            function isFilledString(value) {
                return typeof value === 'string' && value.length > 0;
            }
            class PlainTableBuilder {
                constructor(translationMap, translationPrefix, stub = '-') {
                    this.translationMap = translationMap;
                    this.translationPrefix = translationPrefix;
                    this.stub = stub;
                }
                generateTable(entities) {
                    const firstEntry = entities[0];
                    if (firstEntry) {
                        const keys = Object.keys(firstEntry);
                        const htmlHeader = this.generateHeaderRow(keys);
                        const htmlBody = entities
                            .map((object) => this.generateBodyRow(object, keys))
                            .join('');
                        return `<html><body><table border="1" cellspacing="0"><tbody>${htmlHeader}${htmlBody}</tbody></table></body></html>`;
                    }
                    else {
                        return '';
                    }
                }
                generateHeaderRow(keys) {
                    const htmlCells = keys.map((key) => this.generateHeaderCell(key));
                    return `<tr>${htmlCells.join('')}</tr>`;
                }
                generateBodyRow(entity, keys) {
                    const htmlCells = keys.map((key) => this.generateBodyCell(entity[key]));
                    return `<tr>${htmlCells.join('')}</tr>`;
                }
                generateHeaderCell(key) {
                    const cellValue = this.getTranslatedTitle(key);
                    return `<th>${cellValue}</th>`;
                }
                generateBodyCell(value) {
                    const cellValue = isEmptyValue(value) ? this.stub : value;
                    return `<td>${cellValue}</td>`;
                }
                getTranslatedTitle(key) {
                    const translatePath = isFilledString(this.translationPrefix)
                        ? `${this.translationPrefix}.${key}`
                        : key;
                    return this.translationMap?.[translatePath] ?? key;
                }
            }
            const { translationMap, translationPrefix, entries } = input;
            return new PlainTableBuilder(translationMap, translationPrefix).generateTable(entries);
        }, preparedRequest)
            .then(copyHtml));
    }
    async getTranslationMap() {
        const lang = this.translate.currentLang ?? this.translate.defaultLang;
        const translationMap$ = isNotNil(lang) ? this.translate.getTranslation(lang) : of({});
        return firstValueFrom(translationMap$).then((map) => this.plainTableComposer.composeSingle(map));
    }
}
/** @nocollapse */ TableClipboardService.ɵfac = function TableClipboardService_Factory(t) { return new (t || TableClipboardService)(i0.ɵɵinject(PlainTableComposerService), i0.ɵɵinject(i1.WebWorkerThreadService), i0.ɵɵinject(i3.TranslateService, 8)); };
/** @nocollapse */ TableClipboardService.ɵprov = /** @pureOrBreakMyCode */ i0.ɵɵdefineInjectable({ token: TableClipboardService, factory: TableClipboardService.ɵfac });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TableClipboardService, [{
        type: Injectable
    }], function () { return [{ type: PlainTableComposerService }, { type: i1.WebWorkerThreadService }, { type: i3.TranslateService, decorators: [{
                type: Optional
            }] }]; }, null); })();

class TableClipboardModule {
}
/** @nocollapse */ TableClipboardModule.ɵfac = function TableClipboardModule_Factory(t) { return new (t || TableClipboardModule)(); };
/** @nocollapse */ TableClipboardModule.ɵmod = /** @pureOrBreakMyCode */ i0.ɵɵdefineNgModule({ type: TableClipboardModule });
/** @nocollapse */ TableClipboardModule.ɵinj = /** @pureOrBreakMyCode */ i0.ɵɵdefineInjector({ providers: [WebWorkerThreadService, TableClipboardService], imports: [[PlainTableComposerModule.forRoot()]] });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TableClipboardModule, [{
        type: NgModule,
        args: [{
                imports: [PlainTableComposerModule.forRoot()],
                providers: [WebWorkerThreadService, TableClipboardService]
            }]
    }], null, null); })();
(function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(TableClipboardModule, { imports: [PlainTableComposerModule] }); })();

/**
 * Generated bundle index. Do not edit.
 */

export { PlainTableComposerModule, PlainTableComposerService, TableClipboardModule, TableClipboardService };
//# sourceMappingURL=angular-ru-cdk-table-utils.mjs.map
