import { ApplicationContext, DataType, ElementIDUtils } from '@sankhyalabs/core';
import { h, Host } from '@stencil/core';
import { ApplicationUtils, DialogType } from '@sankhyalabs/ezui/dist/collection/utils';
import { IExportType } from '../../lib/http/data-fetcher/fetchers/fetchDataExporter/interfaces/IFetchDataExporterParams';
import { ItemBuilder } from './structure/ItemBuilder';
import { DataExporterFormat, DataExporterOption, DataExporterType } from '../../lib/@types';
import { REPORT_LAUNCHER_RESOURCE_ID } from '../../lib/utils/constants';
import fileViewer from '../../lib/utils/fileViewer';
import getPersonalizedReports from '../../lib/http/data-fetcher/fetchers/fetchDataExporter/personalized-reports-fetcher';
import { SnkDataUnit } from '../snk-data-unit/snk-data-unit';
import ServerSideExporterStrategy from './exporter-strategy/ServerSideExporterStrategy';
import ClientSideExporterStrategy from './exporter-strategy/ClientSideExporterStrategy';
export class SnkDataExporter {
  constructor() {
    this._selectedNumber = 0;
    this._customPrefix = "$custom$";
    this._releasedToExport = [
      DataExporterOption.EXPORT_TO_PDF,
      DataExporterOption.EXPORT_TO_XLS,
      DataExporterOption.EXPORT_BY_EMAIL,
      DataExporterOption.EXPORT_PDF_TO_EMAIL,
      DataExporterOption.EXPORT_XLS_TO_EMAIL,
      DataExporterOption.EXPORT_PAGE_TO_PDF,
      DataExporterOption.EXPORT_PAGE_TO_XLS,
      DataExporterOption.EXPORT_ALL_RECORDS_TO_PDF,
      DataExporterOption.EXPORT_ALL_RECORDS_TO_XLS,
    ];
    this._items = [];
    this._showDropdown = false;
    this.provider = null;
    this.messagesBuilder = undefined;
  }
  async exportByEmail() {
    const selectedRows = this._selectedNumber;
    const config = {
      type: selectedRows > 0 ? "selection" : "all",
      selectedRows,
      email: {
        attachments: [
          { name: this._appLabel }
        ]
      },
      resolver: ({ type, format, email: { to, subject, message } }) => {
        var _a;
        const methodName = (_a = DataExporterFormat[format === null || format === void 0 ? void 0 : format.toUpperCase()]) !== null && _a !== void 0 ? _a : DataExporterFormat.PDF;
        this.resolveExporter({ type, methodName, to, subject, message, fileName: this._appLabel, gridTitle: this._appLabel }, () => {
          this._snkEmailSender.close();
          ApplicationUtils.info(this.getMessage("snkDataExporter.message.emailSuccess"), { iconName: "check" });
        });
      }
    };
    this._snkEmailSender.open(config);
  }
  /**
   * Conforme mecanismo de mensagens, é possível customizar as mensagens dos blocos de construção
   * através de um pequeno modulo na estrutura da aplicação:
   * - Criar um arquivo no seguinte caminho: /messages/appmessages.msg.js.
   * Para conhecer os detalhes do módulo, vide o arquivo neste projeto "/src/lib/message/resources/snk-data-exporter.msg.ts"
   */
  getMessage(key, params) {
    if (this.messagesBuilder == undefined) {
      const dataUnit = SnkDataUnit.getNearestInstance(this._element);
      if (dataUnit) {
        this.messagesBuilder = dataUnit.messagesBuilder;
      }
    }
    return this.messagesBuilder.getMessage(key, params);
  }
  positionDropdown() {
    var _a;
    const bounding = (_a = this._ezButton) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
    if (bounding == undefined || this._dropdownParent == undefined) {
      return;
    }
    this._dropdownParent.style.top = (bounding.y + bounding.height + 5) + "px";
    this._dropdownParent.style.left = bounding.x + "px";
  }
  closeDropdown(evt) {
    const target = evt === null || evt === void 0 ? void 0 : evt.target;
    if (target == undefined) {
      return;
    }
    if (!target.closest(".snk-data-exporter")) {
      this._showDropdown = false;
    }
  }
  setEvents() {
    document.removeEventListener("click", this.closeDropdown.bind(this));
    document.addEventListener("click", this.closeDropdown.bind(this));
    document.removeEventListener("scroll", this.positionDropdown.bind(this));
    document.addEventListener("scroll", this.positionDropdown.bind(this));
  }
  controlDropdown() {
    this._showDropdown = !this._showDropdown;
  }
  async resolveExporter(resolveProps, callbackResolver) {
    if (this.provider == undefined || resolveProps == undefined || callbackResolver == undefined) {
      return;
    }
    this.getExporterStrategy().executeExport(resolveProps)
      .then((result) => callbackResolver(result))
      .catch((exception) => {
      console.error(exception);
      let { title, message, statusMessage } = exception || {};
      ApplicationUtils.error(title || this.getMessage("snkDataExporter.message.exportError"), statusMessage || message || this.getMessage("snkDataExporter.message.unknownFailure"));
    });
  }
  getExporterStrategy() {
    return this.provider.getRecords == undefined
      ? new ServerSideExporterStrategy(this.provider)
      : new ClientSideExporterStrategy(this.provider);
  }
  getOptionKey(option) {
    return Object.keys(DataExporterOption)
      .find((key) => {
      return DataExporterOption[key] === option;
    });
  }
  getExportType(option) {
    if (option === DataExporterOption.EXPORT_ALL_RECORDS_TO_PDF || option === DataExporterOption.EXPORT_ALL_RECORDS_TO_XLS) {
      return IExportType.ALL;
    }
    if (option === DataExporterOption.EXPORT_PAGE_TO_PDF || option === DataExporterOption.EXPORT_PAGE_TO_XLS) {
      return IExportType.PAGE;
    }
    return IExportType.SELECTION;
  }
  async dispatchExporter(option) {
    var _a, _b, _c;
    const optionKey = this.getOptionKey(option);
    const fileType = (_a = DataExporterType[optionKey]) !== null && _a !== void 0 ? _a : DataExporterType.EXPORT_TO_PDF;
    const params = {
      methodName: DataExporterOption[`EXPORT_TO_${fileType}`],
      fileName: this._appLabel,
      gridTitle: this._appLabel,
      exportOption: option,
      limit: (_c = (_b = this.provider) === null || _b === void 0 ? void 0 : _b.getExportLimit) === null || _c === void 0 ? void 0 : _c.call(_b),
      type: this.getExportType(option),
    };
    await this.resolveExporter(params, (response) => {
      if (response.canExport || fileType === DataExporterType.EXPORT_TO_PDF) {
        fileViewer(Object.assign(Object.assign({}, response), { fileType }));
      }
      else {
        ApplicationUtils.error(this.getMessage("snkDataExporter.title.permission"), this.getMessage("snkDataExporter.message.exportPermission"));
      }
    });
  }
  async processExporter(evt) {
    var _a, _b, _c, _d, _e, _f, _g;
    const item = evt === null || evt === void 0 ? void 0 : evt.detail;
    const exportCurrentPageOptions = [DataExporterOption.EXPORT_PAGE_TO_PDF, DataExporterOption.EXPORT_PAGE_TO_XLS];
    const isCustomReport = (_a = item === null || item === void 0 ? void 0 : item.id) === null || _a === void 0 ? void 0 : _a.includes(this._customPrefix);
    if ((item === null || item === void 0 ? void 0 : item.id) === DataExporterOption.EXPORT_CURRENT_PAGE)
      return;
    const selectedRecords = (_b = this.provider) === null || _b === void 0 ? void 0 : _b.getSelectedIDs();
    const totalRecords = (_c = this.provider) === null || _c === void 0 ? void 0 : _c.getTotalRecords();
    const totalPerPage = (_e = (_d = this.provider) === null || _d === void 0 ? void 0 : _d.getPageSize) === null || _e === void 0 ? void 0 : _e.call(_d);
    const exportLimit = (_g = (_f = this.provider) === null || _f === void 0 ? void 0 : _f.getExportLimit) === null || _g === void 0 ? void 0 : _g.call(_f);
    let limitExceeded = false;
    if ((exportCurrentPageOptions.includes(item === null || item === void 0 ? void 0 : item.id) && totalPerPage <= exportLimit) || isCustomReport) {
      limitExceeded = false;
    }
    else if (selectedRecords === null || selectedRecords === void 0 ? void 0 : selectedRecords.length) {
      limitExceeded = selectedRecords.length > exportLimit;
    }
    else if (totalRecords > exportLimit)
      limitExceeded = true;
    if (limitExceeded) {
      const formattedLimit = exportLimit.toLocaleString('pt-BR', { minimumFractionDigits: 0 });
      const limitModalMessages = {
        title: this.getMessage("snkDataExporter.limitExceeded.title"),
        description: `
          ${this.getMessage("snkDataExporter.limitExceeded.description", { limit: formattedLimit })}
          <br/><br/>
          <b>
          ${this.getMessage("snkDataExporter.limitExceeded.subdescription")}
          </b>
        `,
        cancel: this.getMessage("snkDataExporter.limitExceeded.cancel"),
        confirm: this.getMessage("snkDataExporter.limitExceeded.continue")
      };
      const isAccepted = await ApplicationUtils.confirm(limitModalMessages.title, limitModalMessages.description, null, DialogType.WARN, {
        labelCancel: limitModalMessages.cancel,
        labelConfirm: limitModalMessages.confirm,
      });
      if (!isAccepted)
        return;
    }
    if (isCustomReport) {
      this.openPersonalizedReports(item.id);
      this._showDropdown = false;
      return;
    }
    if (!this.getFilteredReleasedToExport().includes(item === null || item === void 0 ? void 0 : item.id)) {
      return;
    }
    if (item.id === DataExporterOption.EXPORT_BY_EMAIL) {
      this.exportByEmail();
    }
    else {
      this.dispatchExporter(item.id);
    }
    this._showDropdown = false;
  }
  getFilteredReleasedToExport() {
    var _a, _b;
    if (this.provider == undefined) {
      return this._releasedToExport;
    }
    const hiddenOptions = (_b = (_a = this.provider).getHiddenOptions) === null || _b === void 0 ? void 0 : _b.call(_a);
    if (hiddenOptions == undefined) {
      return this._releasedToExport;
    }
    return this._releasedToExport.filter(option => !hiddenOptions.includes(option));
  }
  loadItems() {
    const items = [];
    this.getFilteredReleasedToExport()
      .forEach((option) => {
      var _a;
      (_a = this._itemBuilder) === null || _a === void 0 ? void 0 : _a.setExportOption(option, items);
    });
    this.loadPersonalizedItems(items);
  }
  async loadPersonalizedItems(items) {
    var _a, _b;
    const recordID = (_b = (_a = this.provider) === null || _a === void 0 ? void 0 : _a.getRecordID) === null || _b === void 0 ? void 0 : _b.call(_a);
    if (recordID == undefined) {
      this._items = items;
      return;
    }
    const personalizedReports = await getPersonalizedReports({ recordID });
    personalizedReports === null || personalizedReports === void 0 ? void 0 : personalizedReports.forEach((item) => {
      items.push({
        id: `${this._customPrefix}_${item.ID}`,
        label: item.label,
        group: this.getMessage("snkDataExporter.group.custom")
      });
    });
    this._items = items;
  }
  openPersonalizedReports(option) {
    var _a, _b;
    const pkObject = [];
    const appId = (option === null || option === void 0 ? void 0 : option.replace(this._customPrefix, "")) || "";
    (_b = (_a = this.provider) === null || _a === void 0 ? void 0 : _a.getSelectedIDs) === null || _b === void 0 ? void 0 : _b.call(_a).forEach(({ name, type, value }, index) => {
      const fields = {};
      fields['fields'] = [];
      // Se for o primeiro elemento, adiciona essa primeira PK
      if (index === 0) {
        pkObject[`PK_${name}`] = { type: this.parseDataType(type), value };
        pkObject['pks'] = [];
      }
      const dataFields = { nome: `PK_${name}`, tipo: this.parseDataType(type), valor: value };
      fields['fields'].push(dataFields);
      pkObject['pks'].push(fields);
    });
    this._application.openApp(`${REPORT_LAUNCHER_RESOURCE_ID}${appId}`, pkObject);
  }
  parseDataType(type) {
    switch (type) {
      case DataType.NUMBER:
        return "I";
      case DataType.DATE:
        return "D";
      default:
        return "S";
    }
  }
  loadDropdown() {
    var _a;
    this._selectedNumber = ((_a = this.provider) === null || _a === void 0 ? void 0 : _a.getSelectedNumber()) || 0;
    this._itemBuilder = new ItemBuilder(this.getMessage.bind(this), this._selectedNumber);
    this.loadItems();
  }
  getElementID(sufix) {
    return {
      [ElementIDUtils.DATA_ELEMENT_ID_ATTRIBUTE_NAME]: ElementIDUtils.getInternalIDInfo(sufix)
    };
  }
  canShowDropdown() {
    var _a;
    return this._showDropdown && ((_a = this._items) === null || _a === void 0 ? void 0 : _a.length) > 0;
  }
  componentWillLoad() {
    var _a;
    this._application = ApplicationContext.getContextValue("__SNK__APPLICATION__");
    (_a = this._application) === null || _a === void 0 ? void 0 : _a.getAppLabel().then(result => this._appLabel = result);
    this.setEvents();
  }
  componentDidLoad() {
    if (this._element == undefined) {
      return;
    }
    ElementIDUtils.addIDInfo(this._element);
    this.positionDropdown();
  }
  componentWillUpdate() {
    var _a;
    if (this._showDropdown && !((_a = this._items) === null || _a === void 0 ? void 0 : _a.length)) {
      this.loadDropdown();
    }
  }
  componentDidUpdate() {
    var _a;
    if (this._showDropdown) {
      this.positionDropdown();
    }
    else if (((_a = this._items) === null || _a === void 0 ? void 0 : _a.length) > 0) {
      this._items = [];
    }
  }
  render() {
    return (h(Host, null, h("div", { class: `snk-data-exporter
          ${this.canShowDropdown() ? " ez-elevation--16" : ""}
        ` }, h("ez-button", Object.assign({ ref: (ref) => this._ezButton = ref, iconName: "file-download", size: "small", mode: "icon", title: this.getMessage("snkDataExporter.group.export.title"), onClick: () => this.controlDropdown() }, this.getElementID("button"))), h("div", Object.assign({ ref: (ref) => this._dropdownParent = ref, class: `snk-data-exporter__dropdown
              ${this.canShowDropdown() ? "snk-data-exporter__dropdown--show" : ""}
            ` }, this.getElementID("dropdown")), this.canShowDropdown() &&
      h("ez-dropdown", Object.assign({ items: this._items, onEzClick: (evt) => this.processExporter(evt) }, this.getElementID("dropdown"))))), this.canShowDropdown() &&
      h("div", Object.assign({ class: "ez-scrim ez-scrim--light" }, this.getElementID("ezScrim"))), h("snk-exporter-email-sender", Object.assign({ ref: ref => this._snkEmailSender = ref, getMessage: (key, params) => this.getMessage(key, params) }, this.getElementID("snkExporterEmailSender")))));
  }
  static get is() { return "snk-data-exporter"; }
  static get encapsulation() { return "scoped"; }
  static get originalStyleUrls() {
    return {
      "$": ["snk-data-exporter.css"]
    };
  }
  static get styleUrls() {
    return {
      "$": ["snk-data-exporter.css"]
    };
  }
  static get properties() {
    return {
      "provider": {
        "type": "unknown",
        "mutable": false,
        "complexType": {
          "original": "IExporterProvider",
          "resolved": "IExporterProvider",
          "references": {
            "IExporterProvider": {
              "location": "import",
              "path": "./interfaces/IExporterProvider"
            }
          }
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Provedor das informa\u00E7\u00F5es para exporta\u00E7\u00E3o dos dados."
        },
        "defaultValue": "null"
      },
      "messagesBuilder": {
        "type": "unknown",
        "mutable": true,
        "complexType": {
          "original": "SnkMessageBuilder",
          "resolved": "SnkMessageBuilder",
          "references": {
            "SnkMessageBuilder": {
              "location": "import",
              "path": "../../lib/message/SnkMessageBuilder"
            }
          }
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Respons\u00E1vel por flexibilizar e padronizar o uso de mensagens nos blocos de constru\u00E7\u00E3o."
        }
      }
    };
  }
  static get states() {
    return {
      "_items": {},
      "_showDropdown": {}
    };
  }
  static get elementRef() { return "_element"; }
}
