"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var _react = _interopRequireWildcard(require("react"));
var _get = _interopRequireDefault(require("lodash-es/get"));
var _uniqueId = _interopRequireDefault(require("lodash-es/uniqueId"));
var _classnames = _interopRequireDefault(require("classnames"));
var _faFolderOpen = require("@fortawesome/free-solid-svg-icons/faFolderOpen");
var _faXmark = require("@fortawesome/free-solid-svg-icons/faXmark");
var _useTranslation = require("../hooks/use-translation");
var _fontAwesomeIcon = require("../font-awesome-icon");
var _truncateWithTooltip = require("../truncate-with-tooltip");
var _message = require("../message");
var _dragAndDropWrapper = require("../drag-and-drop-wrapper");
var _progressBar = require("../progress-bar");
var _button = require("../button");
var _dropdownMenu = require("../dropdown-menu");
var _notificationPopup = require("../notification-popup");
var _loadingIcon = require("../loading-icon");
var _fileUploadConstants = require("./file-upload-constants");
var _tooltip = require("../tooltip");
var _hooks = require("../hooks");
var _jsxRuntime = require("react/jsx-runtime");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
// eslint-disable-next-line you-dont-need-lodash-underscore/get

const isFileAccepted = (acceptedFileTypes, file) => acceptedFileTypes?.some(fileType => (0, _get.default)(file, 'name', '').endsWith(fileType));
/** File upload action indicator.
 * [CAPITALIZATION] Use sentence case for input label, no colon
 * [CAPITALIZATION] Helper text usually a complete sentence with a period. Don't have mixed format in one text block. Can be list item with colon (as in "Accepted formats" example), no punctuation at end.
 */
function FileUpload({
  label,
  onFileUploadSuccess,
  serviceHandler,
  acceptedFiles = _fileUploadConstants.DEFAULT_ACCEPTED_FILES,
  onFileUploadFailure,
  isFileValid,
  initialFile,
  inputTestId = 'input-file',
  clearTestId = 'clear-file',
  isLoading,
  uploadPercent,
  isDisabled = false,
  disableDragNDrop = false,
  sourceOptions,
  children,
  triggerTestId = 'custom-source-trigger',
  loadingIconTestId = '',
  loadingIconId = loadingIconTestId,
  showSupportedFilesLabel = true,
  displayValidationErrorsLimit = 10,
  helperText = '',
  disableLocalFileUploading = false,
  tooltipForLocalFileOption = '',
  className = '',
  fileNameTestId = 'file-name-test-id',
  placeholderLabel: placeholderLabelParams,
  uploadProgressLabel: uploadProgressLabelParams,
  failedUploadMessage: failedUploadMessageParams,
  invalidFileTypeMessage: invalidFileTypeMessageParams,
  invalidFileMessage: invalidFileMessageParams,
  acceptedFilesMessage: acceptedFilesMessageParams,
  sourceOptionsTriggerText: sourceOptionsTriggerTextParams,
  clearSelectionText: clearSelectionTextParams,
  localFileOptionText: localFileOptionTextParams,
  browseText: browseTextParams,
  restErrorsAmountMessage: restErrorsAmountMessageParams
}) {
  const {
    t
  } = (0, _useTranslation.useTranslation)();

  // Set default values for text props using the t function with parameters
  const defaultPlaceholderLabel = sourceOptions && sourceOptions.length ? t('Drag and drop a new dataset or select an option from the right') : t('Drag and drop a file here or browse');
  const defaultUploadProgressLabel = t('Uploading file...');
  const defaultFailedUploadMessage = t('Upload failed');
  const defaultInvalidFileTypeMessage = t('Invalid file type, ');
  const defaultInvalidFileMessage = t('Invalid file, ');
  const defaultAcceptedFilesMessage = t('Accepted formats: {{formats}}', {
    formats: acceptedFiles.join(', ')
  });
  const defaultSourceOptionsTriggerText = t('Import from');
  const defaultClearSelectionText = t('Clear selection');
  const defaultLocalFileOptionText = t('Local File');
  const defaultBrowseText = t('Browse');
  const defaultRestErrorsAmountMessage = restErrorsAmount => t('and {{items}} more...', {
    items: restErrorsAmount
  });

  // Use provided values or defaults with nullish coalescing operator
  const placeholderLabel = placeholderLabelParams ?? defaultPlaceholderLabel;
  const uploadProgressLabel = uploadProgressLabelParams ?? defaultUploadProgressLabel;
  const failedUploadMessage = failedUploadMessageParams ?? defaultFailedUploadMessage;
  const invalidFileTypeMessage = invalidFileTypeMessageParams ?? defaultInvalidFileTypeMessage;
  const invalidFileMessage = invalidFileMessageParams ?? defaultInvalidFileMessage;
  const acceptedFilesMessage = acceptedFilesMessageParams ?? defaultAcceptedFilesMessage;
  const sourceOptionsTriggerText = sourceOptionsTriggerTextParams ?? defaultSourceOptionsTriggerText;
  const clearSelectionText = clearSelectionTextParams ?? defaultClearSelectionText;
  const localFileOptionText = localFileOptionTextParams ?? defaultLocalFileOptionText;
  const browseText = browseTextParams ?? defaultBrowseText;
  const restErrorsAmountMessage = restErrorsAmountMessageParams ?? defaultRestErrorsAmountMessage;
  const [entity, setEntityState] = (0, _react.useState)(initialFile);
  const [error, setErrorState] = (0, _react.useState)('');
  const [isUploadPending, setIsUploadPendingState] = (0, _react.useState)(false);
  const [fileInputKey, setFileInputKey] = (0, _react.useState)((0, _uniqueId.default)());
  const fileInputRef = (0, _react.useRef)(null);
  (0, _react.useEffect)(() => {
    if (!entity) {
      setEntityState(initialFile);
    }
  }, [initialFile]);

  // Unique Id prevents <Label htmlFor={ID}> to be linked to another <Input[file] id={ID}> on the page
  const uniqueInputIdRef = (0, _react.useRef)((0, _uniqueId.default)('file-upload-input-'));
  const uniqueLabelIdRef = (0, _react.useRef)((0, _uniqueId.default)('file-upload-label-'));
  const resetStates = () => {
    // reset the file state clear the value
    setEntityState(null);
    setErrorState('');
    // reset file input field
    setFileInputKey(_uniqueId.default);
  };
  const onClearFile = () => {
    resetStates();
    if (onFileUploadSuccess) {
      onFileUploadSuccess(null);
    }
  };
  const handleFileUpload = uploadFile => {
    const onHandleFileUploadSuccess = response => {
      if (onFileUploadSuccess) {
        onFileUploadSuccess(response);
      }
    };
    const onHandleFileUploadFailure = err => {
      if (Array.isArray(err)) {
        // throwing an array of file's validation errors
        return setErrorState(err);
      }
      _notificationPopup.NotificationService.error((0, _get.default)(err, 'message', failedUploadMessage));
      resetStates();
      if (onFileUploadFailure) {
        onFileUploadFailure(err);
      }
    };
    const onHandleFileUploadDone = () => {
      setEntityState(uploadFile);
      setIsUploadPendingState(false);
    };
    if (serviceHandler) {
      setIsUploadPendingState(true);
      serviceHandler(uploadFile).then(onHandleFileUploadSuccess).catch(onHandleFileUploadFailure).finally(onHandleFileUploadDone);
    } else {
      setEntityState(uploadFile);
      if (onFileUploadSuccess) {
        onFileUploadSuccess(uploadFile);
      }
    }
  };
  const handleFileUploadValidation = selectedFile => {
    setErrorState('');
    if (acceptedFiles.length && !isFileAccepted(acceptedFiles, selectedFile)) {
      return setErrorState(invalidFileTypeMessage);
    }

    // if upload prop validator provided
    if (typeof isFileValid === 'function' && selectedFile && !isFileValid(selectedFile, acceptedFiles)) {
      return setErrorState(invalidFileMessage);
    }
    return handleFileUpload(selectedFile);
  };
  const onFileUploaded = e => {
    e.preventDefault();
    const selectedFile = e.target?.files?.[0];
    return handleFileUploadValidation(selectedFile);
  };
  const onDrop = ({
    files
  }) => {
    const selectedFile = files && files[0];
    setEntityState(null);
    handleFileUploadValidation(selectedFile);
  };
  const hasCustomSelector = () => sourceOptions && sourceOptions.length;
  const renderPlaceholder = () => {
    const fileName = entity?.name || placeholderLabel;
    return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
      className: "file-placeholder placeholder",
      "test-id": "file-placeholder",
      children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_truncateWithTooltip.TruncateWithTooltip, {
        tooltipPlacement: _tooltip.TOOLTIP_PLACEMENT_TYPES.BOTTOM,
        className: "file-name",
        children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
          "test-id": fileNameTestId,
          children: fileName
        })
      })
    });
  };
  const renderLayout = selector => {
    return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
      children: [renderPlaceholder(), !entity && selector]
    });
  };
  const renderDefaultFileInput = () => {
    const attrs = (0, _hooks.getNonNativeButtonAttrs)({
      isDisabled,
      onKeyDown: () => {
        fileInputRef.current?.click?.();
      }
    });
    return /*#__PURE__*/(0, _jsxRuntime.jsx)("label", {
      className: (0, _classnames.default)('button command choose-file-btn', {
        disabled: isDisabled
      }),
      "test-id": "choose-file-btn-label",
      htmlFor: uniqueInputIdRef.current,
      children: renderLayout(/*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
        className: "browse-button",
        ...attrs,
        "aria-describedby": uniqueLabelIdRef.current,
        children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_fontAwesomeIcon.FontAwesomeIcon, {
          icon: _faFolderOpen.faFolderOpen
        }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
          "test-id": "browse-text",
          children: browseText
        })]
      }))
    });
  };
  const renderSourceOptions = () => {
    const options = [{
      id: 'local-file-option',
      key: 'local-file-option',
      testId: 'local-file-option',
      title: localFileOptionText,
      onOptionSelect: () => {
        if (fileInputRef.current) {
          fileInputRef.current.click();
        }
      },
      disabled: disableLocalFileUploading,
      tooltipText: tooltipForLocalFileOption
    }];
    if (sourceOptions?.length) {
      options.push(...sourceOptions);
    }
    return renderLayout(/*#__PURE__*/(0, _jsxRuntime.jsx)(_dropdownMenu.DropdownMenu, {
      isDisabled: isDisabled,
      options: options,
      defaultTriggerText: sourceOptionsTriggerText,
      triggerTestId: triggerTestId,
      onSelect: option => {
        if (option?.onOptionSelect) {
          option.onOptionSelect();
        }
      },
      contentTestId: "file-upload-dropdown-menu"
    }));
  };
  const renderProgress = () => {
    const isProgressTracking = uploadPercent || uploadPercent === 0;
    return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
      className: (0, _classnames.default)('file-upload-progress', isProgressTracking && 'file-upload-percent'),
      children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_loadingIcon.LoadingIcon, {
        message: uploadProgressLabel,
        testId: loadingIconTestId,
        id: loadingIconId
      }), isProgressTracking && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
        children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_progressBar.ProgressBar, {
          max: 100,
          value: uploadPercent,
          ariaLabelledBy: loadingIconId
        }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
          className: "file-upload-percent-text",
          "test-id": "file-upload-percent-text",
          children: [uploadPercent, "%"]
        })]
      })]
    });
  };
  const renderContent = () => {
    return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
      children: [hasCustomSelector() ? renderSourceOptions() : renderDefaultFileInput(), /*#__PURE__*/(0, _jsxRuntime.jsx)("input", {
        type: "file",
        id: uniqueInputIdRef.current,
        ref: fileInputRef,
        "test-id": inputTestId,
        onChange: onFileUploaded,
        disabled: isDisabled,
        accept: acceptedFiles.toString()
      }, fileInputKey)]
    });
  };
  const renderServerValidationErrors = errors => {
    const restErrorsAmount = errors.length - displayValidationErrorsLimit;
    return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
      className: "validation-errors",
      "test-id": "file-upload-validation-errors",
      children: [errors.slice(0, displayValidationErrorsLimit).map((err, i) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_message.Message, {
        type: _message.MESSAGE_TYPES.ERROR,
        testId: "file-upload-message-error",
        children: err
      }, i)), restErrorsAmount > 0 && /*#__PURE__*/(0, _jsxRuntime.jsx)(_message.Message, {
        type: _message.MESSAGE_TYPES.ERROR,
        children: restErrorsAmountMessage(restErrorsAmount)
      })]
    });
  };
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
    className: (0, _classnames.default)('file-upload-input', className),
    "test-id": "file-upload-input",
    children: [label && /*#__PURE__*/(0, _jsxRuntime.jsx)("label", {
      className: (0, _classnames.default)('file-upload-field-label', {
        'supported-files': showSupportedFilesLabel && Boolean(acceptedFiles.length)
      }),
      htmlFor: uniqueInputIdRef.current,
      children: label
    }), helperText && /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
      className: "file-upload-helper-text",
      children: helperText
    }), showSupportedFilesLabel && Boolean(acceptedFiles.length) && /*#__PURE__*/(0, _jsxRuntime.jsx)("label", {
      className: "supported-files-label",
      "test-id": "supported-files-label",
      id: uniqueLabelIdRef.current,
      children: acceptedFilesMessage
    }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_dragAndDropWrapper.DragNDropWrapper, {
      onDropAction: onDrop,
      isDisabled: disableDragNDrop,
      children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
        className: (0, _classnames.default)('file-input-group', {
          disabled: isDisabled || isLoading || isUploadPending
        }),
        "test-id": "file-input-group-container",
        children: [isUploadPending || isLoading ? renderProgress() : renderContent(), entity && !(isUploadPending || isLoading) && !isDisabled && /*#__PURE__*/(0, _jsxRuntime.jsxs)("button", {
          type: _button.BUTTON_TYPES.BUTTON,
          className: "button command choose-file-btn",
          "test-id": clearTestId,
          onClick: onClearFile,
          disabled: isDisabled,
          children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_fontAwesomeIcon.FontAwesomeIcon, {
            icon: _faXmark.faXmark
          }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
            children: clearSelectionText
          })]
        })]
      })
    }), Boolean(error) && (Array.isArray(error) ? renderServerValidationErrors(error) : /*#__PURE__*/(0, _jsxRuntime.jsxs)(_message.Message, {
      type: _message.MESSAGE_TYPES.ERROR,
      testId: "file-upload-message-error",
      children: [error, acceptedFilesMessage]
    })), hasCustomSelector() && typeof children === 'function' && !entity && children({
      handleEntitySelected: setEntityState
    })]
  });
}
var _default = exports.default = FileUpload;