<script lang="tsx">
import {
  defineComponent,
  nextTick,
  onMounted,
  ref,
  watch,
  type Events,
  type PropType,
} from 'vue'
import Tooltip from '../tooltips/BlackTooltip.vue'
import ICONS from './icons'

type ActionSettings = {
  tooltipText: string
  icon: keyof typeof ICONS
  onClick(): void

  positionCorrectingX?: number
  positionCorrectingY?: number
}

/**
 * Кнопка запускает действие, а текст или иконка информирует о том, что произойдет после нажатия.
 *
 * <p>
 *   <a href="https://www.figma.com/file/Q4Z4CnFx4i0qhD5fbgnPpf/%F0%9F%92%BB-%D0%94%D0%B8%D0%B7%D0%B0%D0%B9%D0%BD-%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B0-ARK-SPACE?node-id=0%3A1&mode=dev" target="_blank">Дизайн</a>
 * </p>
 */
export default defineComponent({
  props: {
    /**
     * Флаг, указывающий, отключена ли кнопка
     */
    isDisabled: {
      type: Boolean,
      default: false,
    },

    /**
     * Состояние лоадера в кнопке
     */
    isLoading: {
      type: Boolean,
      default: false,
    },

    /**
     * Флаг, указывающий, есть ли ошибка \
     * При `true` подключаются стили кнопки с ошибками
     */
    isError: {
      type: Boolean,
      default: false,
    },

    /**
     * Позволяет отображать `tooltip` (подсказку) рядом с кнопкой \
     * Подсказка отображается только тогда, когда текст в кнопке выходит за его рамки
     */
    isShowTooltip: {
      type: Boolean,
      default: false,
    },

    /**
     * Активное состояние кнопки
     */
    isActive: {
      type: Boolean,
      default: false,
    },

    /**
     * Настройка отображения дополнительной кнопки взаимодействия
     */
    action: {
      type: Object as PropType<ActionSettings>,
      default: undefined,
    },

    /**
     * Размер кнопки
     *
     * @prop 'M' - большой
     * @prop 'S' - маленький
     */
    size: {
      type: String as PropType<'M' | 'S'>,
      default: 'M',
    },

    /**
     * Тип кнопки в соответствии с дизайном
     */
    type: {
      type: String as PropType<'primary' | 'secondary' | 'tertiary' | 'critical'>,
      default: 'primary',
    },
    /**
     * Текст кнопки
     */
    label: {
      type: String,
      default: undefined,
    },

    /**
     * Дополнительные классы для стилизации
     */
    className: {
      type: String,
      default: '',
    },

    /**
     * Иконка кнопки, выбранная из предопределенного набора `ICONS`
     */
    icon: {
      type: String as PropType<keyof typeof ICONS>,
      default: undefined,
    },
    /**
     * Кастомная иконка кнопки
     *
     * ! Перезаписывает пропс "icon"
     */
    customIcon: {
      type: Function as PropType<() => JSX.Element>,
      default: undefined,
    },

    /**
     * Кастомный цвет всей кнопки
     */
    color: {
      type: String,
      default: '',
    },

    /**
     * Кастомный цвет кнопки при наведении
     */
    colorHover: {
      type: String,
      default: '',
    },

    /**
     * Отображение пользовательского контента справа
     */
    rightSlot: {
      type: Function as PropType<() => JSX.Element>,
      default: undefined,
    },

    /**
     * Кастомный цвет отключенной кнопки \
     * т.е. если `isDisabled: true`
     */
    colorDisabled: {
      type: String,
      default: '',
    },

    onClick: {
      type: Function as PropType<(e: Events['onClick']) => any>,
      default: () => () => {},
    },
  },

  setup(props) {
    const isLabelValueMoreThanLabelWidth = ref(false)
    const labelElement = ref<HTMLSpanElement | null>(null)

    const checkLabelSize = async () => {
      if (!labelElement.value) return

      await nextTick()

      isLabelValueMoreThanLabelWidth.value = labelElement.value?.scrollWidth > labelElement.value?.clientWidth
    }

    watch(() => props.label, checkLabelSize)

    onMounted(checkLabelSize)

    return () => {
      const buttonElement = () => (
        <div class="ark-ui-button-wrapper">
          <button
            class={`
              ark-ui-button
              ${props.isActive ? 'active' : ''}
              ${props.isShowTooltip ? 'with-tooltip' : ''}
              ${props.size.toLowerCase()}
              ${props.type}
              ${props.className}
              ${props.icon || props.isLoading ? 'with-icon' : ''}
              ${props.color ? 'color' : ''}
              ${props.isError ? 'with-error' : ''}
              ${props.action && !props.isDisabled ? 'with-action' : ''}`}
            style={`
              ${props.color ? `--color: ${props.color};` : ''}
              ${props.colorDisabled ? `--colorDisabled: ${props.colorDisabled};` : ''}
              ${props.colorHover ? `--colorHover: ${props.colorHover}` : ''}`}
            disabled={props.isDisabled}

            onClick={props.onClick}
          >
            {props.isLoading ? (
              <span class='ark-ui-button-icon ark-ui-button-icon-loader'>{ ICONS.loaderTwo }</span>
            ) : props.customIcon
              ? <span class='ark-ui-button-icon'>{ props.customIcon() }</span>
              : ((props.icon && props.icon in ICONS)
                ? <span class='ark-ui-button-icon'>{ ICONS[props.icon] }</span>
                : ''
              )}

            {props.label
              ? <span ref={labelElement} class='ark-ui-button-label'>{ props.label }</span>
              : ''
            }
            {props.rightSlot ? props.rightSlot() : ''}
          </button>

          { props.action && !props.isDisabled && (
            <Tooltip text={props.action.tooltipText} positionCorrectingX={props.action.positionCorrectingX} positionCorrectingY={props.action.positionCorrectingY}>
              <div class="ark-ui-button-action" onClick={props.action.onClick}>
                { ICONS[props.action.icon] }
              </div>
            </Tooltip>
          ) }
        </div>
      )

      return (
        <>
          {
            props.isShowTooltip && isLabelValueMoreThanLabelWidth.value && props.label
              ? (
                <Tooltip text={props.label} class="ark-ui-button-tooltip">
                  { buttonElement() }
                </Tooltip>
              )
              : buttonElement()
          }
        </>
      )
    }
  },
})
</script>

<style lang="scss">
@import './assets/styles.scss';

.ark-ui-button-tooltip {
  width: 100% !important;

  .ark-ui-tooltip-cloud {
    max-width: 100%;
    word-break: break-word;
  }
}
</style>

<style lang="scss" scoped>
.ark-ui-button.with-tooltip {
  width: 100%;

  .ark-ui-button-label {
    display: block;
    overflow: hidden;

    white-space: nowrap;
    text-overflow: ellipsis;
  }
}
</style>
