import * as ExportRedux from '../../Redux/ActionsReducers/ExportRedux';
import { ApiBase } from './ApiBase';
import * as ModuleConstants from '../../Utilities/Constants/ModuleConstants';
import { ExportInternalApi } from '../Internal/ExportInternalApi';
import { ALL_DATA_REPORT, EMPTY_STRING, SYSTEM_EXPORT_DESTINATIONS, SYSTEM_REPORT_FORMATS, SYSTEM_REPORT_NAMES, VISUAL_EXCEL_FORMAT_REPORT, } from '../../Utilities/Constants/GeneralConstants';
export class ExportApiImpl extends ApiBase {
    constructor(_adaptable) {
        super(_adaptable);
        this.internalApi = new ExportInternalApi(_adaptable);
    }
    getExportState() {
        return this.getAdaptableState().Export;
    }
    getCurrentReportName() {
        return this.getExportState().CurrentReport;
    }
    getCurrentReportFormat() {
        return this.getExportState().CurrentFormat;
    }
    getCurrentReport() {
        const reportName = this.getCurrentReportName();
        return this.getReportByName(reportName);
    }
    getReportByName(reportName) {
        // if system report then create
        if (this.internalApi.isSystemReport(reportName)) {
            return this.internalApi.createSystemReport(reportName);
        }
        const customReport = this.getCustomReports().find((r) => r.Name == reportName);
        if (customReport) {
            return customReport;
        }
    }
    getReportById(id) {
        return this.getAllReports()?.find((report) => report.Uuid === id);
    }
    getDestinationByName(destinationName) {
        if (this.internalApi.isSystemDestination(destinationName)) {
            return destinationName;
        }
        return this.getCustomDestinations().find((destination) => destination.name === destinationName);
    }
    getAvailableSystemReports() {
        const systemReportNamesOption = this.getExportOptions().systemReportNames;
        const reportNames = typeof systemReportNamesOption === 'function'
            ? systemReportNamesOption({
                ...this.getAdaptableInternalApi().buildBaseContext(),
                defaultSystemReportNames: SYSTEM_REPORT_NAMES,
                currentLayoutName: this.getLayoutApi().getCurrentLayoutName(),
            })
            : systemReportNamesOption;
        return reportNames.filter((s) => this.internalApi.isSystemReportActive(s));
    }
    getAvailableSystemFormats() {
        const systemReportFormatsOption = this.getExportOptions().systemReportFormats;
        const reportFormats = typeof systemReportFormatsOption === 'function'
            ? systemReportFormatsOption({
                ...this.getAdaptableInternalApi().buildBaseContext(),
                defaultSystemReportFormats: SYSTEM_REPORT_FORMATS,
                currentLayoutName: this.getLayoutApi().getCurrentLayoutName(),
                currentReportName: this.getExportApi().getCurrentReportName(),
            })
            : systemReportFormatsOption;
        return reportFormats.filter((format) => {
            // JSON format doesn't support Master Detail Grid
            if (this.getGridApi().isMasterDetailGrid()) {
                return format !== 'JSON';
            }
            // PivotLayout & AllData can't be exported as VisualExcel
            if (this.getExportApi().getCurrentReportName() === ALL_DATA_REPORT &&
                this.getLayoutApi().isCurrentLayoutPivot()) {
                return format !== 'VisualExcel';
            }
            return true;
        });
    }
    getAvailableSystemDestinations() {
        const systemExportDestinationsOption = this.getExportOptions().systemExportDestinations;
        const systemExportDestinations = typeof systemExportDestinationsOption === 'function'
            ? systemExportDestinationsOption({
                ...this.getAdaptableInternalApi().buildBaseContext(),
                defaultSystemExportDestinations: SYSTEM_EXPORT_DESTINATIONS,
                currentLayoutName: this.getLayoutApi().getCurrentLayoutName(),
                currentReportName: this.getExportApi().getCurrentReportName(),
                currentReportFormat: this.getExportApi().getCurrentReportFormat(),
            })
            : systemExportDestinationsOption;
        return systemExportDestinations.filter((destination) => {
            // VisualExcel format can't be exported to custom destinations
            if (this.getExportApi().getCurrentReportFormat() === VISUAL_EXCEL_FORMAT_REPORT) {
                return false;
            }
            return true;
        });
    }
    getAllExportDestinations() {
        const destinationItems = [
            ...this.getAvailableSystemDestinations(),
            ...this.getCustomDestinations().map((destination) => destination.name),
        ];
        return destinationItems;
    }
    getAllFormats() {
        // FIXME AFL: add here custom formats when available
        return this.getAvailableSystemFormats();
    }
    getAllReports() {
        const reports = this.getAvailableSystemReports()
            .map((s) => this.getReportByName(s))
            .concat(this.getExportState().Reports);
        return reports;
    }
    selectReport(reportName) {
        this.dispatchAction(ExportRedux.ReportSelect(reportName));
    }
    clearReport() {
        this.selectReport(EMPTY_STRING);
    }
    selectFormat(reportFormat) {
        this.dispatchAction(ExportRedux.FormatSelect(reportFormat));
    }
    clearFormat() {
        this.selectFormat(null);
    }
    getCustomDestinations() {
        return this.getExportOptions().customDestinations ?? [];
    }
    isExportDestinationCustom(destinationName) {
        return this.getCustomDestinations().some((destination) => destination.name === destinationName);
    }
    getExportDestinationForm(destinationName) {
        return this.getCustomDestinations().find((destination) => destination.name === destinationName)
            ?.form;
    }
    canExportToExcel() {
        return this._adaptable.canExportToExcel();
    }
    canExportToCsv() {
        return this._adaptable.canExportToCsv();
    }
    openExportSettingsPanel() {
        this.showModulePopup(ModuleConstants.ExportModuleId);
    }
    updateReport(report) {
        this.dispatchAction(ExportRedux.ReportEdit(report));
        return this.getReportById(report.Uuid);
    }
    updateReports(reports) {
        reports.forEach((report) => {
            this.updateReport(report);
        });
        return reports?.map((report) => this.getReportById(report.Uuid));
    }
    getCustomReports() {
        return this.getExportState().Reports ?? [];
    }
    isColumnExportable(adaptableColumn) {
        const isExportableFn = this.getExportOptions().isColumnExportable;
        if (typeof isExportableFn === 'function') {
            const adaptableColumnContext = {
                ...this.getAdaptableInternalApi().buildBaseContext(),
                column: adaptableColumn,
            };
            return isExportableFn(adaptableColumnContext);
        }
        return true;
    }
    getSupportedExportDestinations(reportFormat) {
        if (reportFormat == undefined) {
            return [];
        }
        return this.getExportApi()
            .getAllExportDestinations()
            .filter((destination) => {
            // can NOT export BLOBs to Clipboard
            if (reportFormat === 'Excel' || reportFormat === 'VisualExcel') {
                return destination !== 'Clipboard';
            }
            return true;
        });
    }
    async exportReport(reportName, format, destination = 'Download', config) {
        let report = this.getReportByName(reportName);
        if (!this.checkItemExists(report, reportName, 'Report')) {
            return;
        }
        this.logInfo(`Start Export of ${reportName} in format ${format} to ${destination}`);
        const processExportResult = await this.processExport(report, format, destination);
        // if FALSE, cancel export
        if (!processExportResult) {
            this.logInfo(`Cancel Export of ${reportName}`);
            return;
        }
        // if TRUE, continue with standard export
        if (processExportResult === true) {
            const exportedReport = await this._adaptable.agGridExportAdapter.exportData({
                report,
                format,
                destination,
                showProgressIndicator: config?.showProgressIndicator === false ? false : true,
                customExportParams: config?.exportParams,
            });
            if (!exportedReport) {
                // for destination 'Download' and format 'Excel', 'VisualExcel' or 'Csv', AG Grid handles the download as well
                return;
            }
            this.internalApi.sendReportToDestination(exportedReport, report, format, destination);
        }
        else {
            // in this case the user has returned a custom ExportResultData object
            const userProcessedExportResult = processExportResult;
            if (!userProcessedExportResult) {
                this.logWarn(`Processing of Export ${reportName} to ${destination} returned null or undefined`);
                return;
            }
            this.internalApi.sendReportToDestination(userProcessedExportResult, report, format, destination);
        }
        this.logInfo(`Finished Export of ${reportName} in format ${format} to ${destination}`);
    }
    async getReportData(reportName, format, config) {
        let report = this.getReportByName(reportName);
        if (!this.checkItemExists(report, reportName, 'Report')) {
            return;
        }
        this.logInfo(`Start getting Report Data for ${reportName} in format ${format}`);
        const processExportResult = await this.processExport(report, format, 'Clipboard');
        let reportData;
        // handle Export processing
        if (typeof processExportResult?.type === 'string') {
            reportData = processExportResult;
        }
        else {
            reportData = await this._adaptable.agGridExportAdapter.exportData({
                report,
                format,
                destination: 'Clipboard',
                showProgressIndicator: config?.showProgressIndicator === false ? false : true,
                customExportParams: config?.exportParams,
            });
        }
        this.logInfo(`Finished getting Report Data for ${reportName} in format ${format}`);
        return reportData;
    }
    async processExport(report, format, destination) {
        const processExportFn = this.getExportOptions().processExport;
        if (!processExportFn) {
            return true;
        }
        this.logInfo(`Process Export of ${report.Name} in format ${format} to ${destination}`);
        const processExportContext = this.internalApi.buildProcessExportContext(report, format, destination);
        return processExportFn(processExportContext);
    }
}
