import { UniDriver, waitFor } from '@wix/wix-ui-test-utils/unidriver';
import { baseUniDriverFactory } from '../../unidriver';
import { PickerUniDriver } from '../Picker/Picker.uni.driver';
import {
  ModalUniDriver,
  TextButtonUniDriver,
  TextUniDriver,
} from '@wix/design-system/dist/testkit/unidriver';
import { PickerModalLayoutUniDriver } from './PickerModalLayout.uni.driver';

export function PickerModalUniDriver(
  base: UniDriver,
  body: UniDriver,
  { dataHook }: { dataHook?: string } = {},
) {
  const modalBase = () =>
    body.$(
      dataHook
        ? `.portal-${dataHook}-picker-modal`
        : '.portal-picker-modal-lazy-modal',
    );
  const modal = () => ModalUniDriver(modalBase(), modalBase());

  const layout = () => PickerModalLayoutUniDriver(modalBase(), body);

  const picker = () =>
    PickerUniDriver(modalBase().$('[data-hook="picker"]'), body);

  const additionalStepDriver = () => {
    return {
      title: () =>
        TextUniDriver(modalBase().$('[data-hook="title"]'), body).getText(),
      subtitle: () =>
        TextUniDriver(modalBase().$('[data-hook="subtitle"]'), body).getText(),
      suffixText: () =>
        TextUniDriver(
          modalBase().$('[data-hook="suffix-text"]'),
          body,
        ).getText(),
      suffixNode: () => modalBase().$('[data-hook="suffix-node"]'),
    };
  };

  const getNoResultsSubtitle = () =>
    TextUniDriver(
      body.$('[data-hook="picker-no-results-state-subtitle"]'),
      body,
    );

  const getNoResultsResetButton = () =>
    TextButtonUniDriver(
      body.$('[data-hook="picker-no-results-state-reset-button"]'),
      body,
    );

  return {
    ...baseUniDriverFactory(base),
    isOpen: () => modal().isOpen(),
    wait: (timeout?: number) => base.wait(timeout),
    modalLayoutExists: () => layout().exists(),
    pickerExists: () => picker().exists(),
    waitPicker: (timeout?: number) => picker().wait(timeout),
    waitModalClosed: (timeout?: number) =>
      waitFor(async () => !(await picker().exists()), timeout),
    /** Indicates whether the modal is open */
    isModalOpen: () => modal().isOpen(),
    /** Get the modal layout title text */
    getTitleText: () => layout().getTitleText(),
    /** Get the modal layout subtitle text */
    getSubtitleText: () => layout().getSubtitleText(),
    /** Clear the search input */
    clearSearchTerm: () => layout().clearSearchTerm(),
    /** Enter a value to the search input */
    enterSearchTerm: (value: string) => layout().enterSearchTerm(value),
    /** Get the value of the search input  */
    getSearchTerm: () => layout().getSearchTerm(),
    /** Get the placeholder of the search input */
    getSearchPlaceholder: () => layout().getSearchPlaceholder(),
    searchExists: () => layout().searchExists(),
    waitSearchLoader: (timeout?: number) => picker().waitSearchLoader(timeout),
    waitSearchLoaderRemoved: (timeout?: number) =>
      picker().waitSearchLoaderRemoved(timeout),
    floatingNotificationExists: () => picker().floatingNotificationExists(),
    /**
     * Get the text of the floating notification at the top of the list
     */
    getFloatingNotificationText: () => picker().getFloatingNotificationText(),
    waitInitialLoader: (timeout?: number) =>
      layout().waitInitialLoader(timeout),
    waitInitialLoaderRemoved: (timeout?: number) =>
      layout().waitInitialLoaderRemoved(timeout),

    /** Get the number of rows currently rendered inside the selector list */
    numberOfItemsInList: () => picker().numberOfItemsInList(),
    /** Get the number of selected rows */
    getTotalSelected: () => picker().getTotalSelected(),
    /**
     * Triggers "scroll" event on the list.
     */
    scrollDown: () => picker().scrollDown(),
    /**
     * Toggles selector of the item at the passed index.
     * @param {number} index Item index
     * @returns {Promise<void>} Resolves when selector is toggled.
     */
    toggleSelectorAt: (index: number) => picker().toggleSelectorAt(index),
    /**
     * Checks whether the selector of the item at the passed index is checked.
     * @param {number} index Item index
     * @returns {Promise<boolean>}
     */
    isSelectorCheckedAt: (index: number) => picker().isSelectorCheckedAt(index),
    /**
     * Checks whether the item at the passed index is disabled.
     * @param {number} index Item index
     * @returns {Promise<boolean>}
     */
    isListItemDisabledAt: (index: number) =>
      picker().isListItemDisabledAt(index),
    /**
     * Wait for a item to be added to the list
     * @param index
     * @param timeout
     */
    waitListItemAt: (index: number, timeout?: number) =>
      picker().waitListItemAt(index, timeout),
    /**
     * Get the title text of a list item
     * @param index
     */
    getTitleTextAt: (index: number) => picker().getTitleTextAt(index),
    /** Indicates whether item checkbox is in indeterminate mode  */
    isIndeterminateAt: (index: number) => picker().isIndeterminateAt(index),
    /**
     * Get the sub-title text of a list item
     * @param index
     */
    getSubtitleTextAt: (index: number) => picker().getSubtitleTextAt(index),
    /**
     * Get the image element of a list item
     * @param index
     */
    getImageElementAt: (index: number) => picker().getImageElementAt(index),
    /**
     * Get the extra node element of a list item
     * @param index
     */
    getExtraNodeElementAt: (index: number) =>
      picker().getExtraNodeElementAt(index),
    /**
     * Get the tooltip toggle text of a list item
     * @param index
     */
    getToggleTooltipTextAt: (index: number) =>
      picker().getToggleTooltipTextAt(index),
    /**
     * Indicates whether the initial loader of the modal is shown
     */
    initialLoaderExists: () => layout().initialLoaderExists(),

    /** Get empty state within the modal that by a specific data hook */
    getEmptyStateByDataHook: (dataHook: string) =>
      picker().getEmptyStateByDataHook(dataHook),

    /** Indicates whether the loader after search exists */
    searchLoaderExists: () => picker().searchLoaderExists(),

    /** Indicates whether the CTA button exists */
    ctaButtonExists: () => layout().ctaButtonExists(),
    /** Click the CTA button of the modal */
    clickCTAButton: () => layout().clickCTAButton(),
    /** Click the back button on the additional step */
    clickBackButton: () => layout().clickBackButton(),
    /** Indicates whether the back button exists on the additional step */
    backButtonExists: () => layout().backButtonExists(),
    /** Get the text of the suffix content if exists on the additional step */
    additionalStepSuffixText: () => additionalStepDriver().suffixText(),
    /** Get the node of the suffix content if exists on the additional step */
    additionalStepSuffixNode: () => additionalStepDriver().suffixNode(),
    /** Get the text of the item title on the additional step */
    additionalStepTitleText: () => additionalStepDriver().title(),
    /** Get the text of the item subtitle on the additional step */
    additionalStepSubtitleText: () => additionalStepDriver().subtitle(),
    /** Click modal cancel button **/
    clickCancelButton: () => layout().clickCancelButton(),
    /** Get the text of the cancel button */
    getCancelButtonText: () => layout().getCancelButtonText(),
    /** Indicates whether the cancel button exists */
    cancelButtonExists: () => layout().cancelButtonExists(),
    /** Click modal close (x) button **/
    clickCloseButton: () => layout().clickCloseButton(),
    /** Get the text of the CTA button */
    getCTAButtonText: () => layout().getCTAButtonText(),
    /** Indicates whether the CTA button is disabled */
    isCTAButtonDisabled: () => layout().isCTAButtonDisabled(),
    /** Get the error state before the modal content is fetched */
    getSplashErrorStateByDataHook: (dataHook: string) =>
      layout().getErrorStateByDataHook(dataHook),
    /** Get the error state within the modal content */
    getErrorStateByDataHook: (dataHook: string) =>
      picker().getEmptyStateByDataHook(dataHook),
    customContentButtonExists: () => layout().customContentButtonExists(),
    getCustomContentButtonText: () => layout().getCustomContentButtonText(),
    isCustomContentButtonDisabled: () =>
      layout().isCustomContentButtonDisabled(),
    customContentButtonTooltipExists: () =>
      layout().customContentButtonTooltipExists(),
    getCustomContentButtonTooltipText: () =>
      layout().getCustomContentButtonTooltipText(),
    clickCustomContentButton: () => layout().clickCustomContentButton(),
    getMaxSelectionLabelText: () => layout().getMaxSelectionLabelText(),
    getSelectAllCheckbox: () => layout().getSelectAllCheckbox(),
    getSelectedItemsCountText: () => layout().getSelectedItemsCountText(),
    customNotificationExists: () => layout().customNotificationExists(),

    getFilterDropdown: (filterName: string) =>
      layout().getFilterDropdown(filterName),
    filterDropdownExists: (filterName: string) =>
      layout().filterDropdownExists(filterName),
    getSelectedFilterName: (filterName: string) =>
      layout().getSelectedFilterName(filterName),
    selectFilterItem: (filterName: string, index: number) =>
      layout().selectFilterItem(filterName, index),
    selectFilterItems: (filterName: string, ids: string[]) =>
      layout().selectFilterItems(filterName, ids),
    getNoResultsSubtitle,
    getNoResultsResetButton,
  };
}

export default PickerModalUniDriver;
