<script lang="tsx">
import moment, { type Moment } from 'moment'
import {
  type PropType, type Ref, defineComponent, ref,
} from 'vue'
import Clock from './assets/clock'
import Close from './assets/close'
import { copyTooltip } from '../../helpers'

/**
 * Инпут выбора времени
 */
export default defineComponent({
  props: {
    /**
     * Состояние инпута
     */
    isDisabled: {
      type: Boolean,
      default: false,
    },
    /**
     * Показывать/не показывать заголовок
     */
    isShowLabel: {
      type: Boolean,
      default: true,
    },

    /**
     * Опция копирования значения
     */
    isWithCopy: {
      type: Boolean,
      default: false,
    },

    /**
     * Текст заголовка
     */
    label: {
      type: String,
      default: '',
    },
    /**
     * Плейсхолдер
     */
    placeholder: {
      type: String,
      default: '00',
    },
    /**
     * Массив ошибок
     */
    errors: {
      type: Array as PropType<string[]>,
      default: () => [],
    },

    /**
     * Значение инпута
     */
    modelValue: {
      type: Object as PropType<Moment | null>,
      required: true,
    },
    /**
     * Функция смены значения
     */
    onValueChange: {
      type: Function as PropType<(v: Moment | null) => void>,
      required: true,
    },
  },

  setup(props) {
    let isFirstFocus = true
    const hoursInput: Ref<HTMLInputElement | null> = ref(null)
    const minutesInput: Ref<HTMLInputElement | null> = ref(null)

    const toggleIsFirstFocus = (val: boolean) => {
      isFirstFocus = val
    }

    const copy = (event: MouseEvent) => {
      if (!props.isWithCopy) return

      copyTooltip(props.modelValue?.format('HH:mm') ?? '', event.clientX + 10, event.clientY - 30)
    }

    const clickHandler = (event: MouseEvent) => {
      copy(event)

      hoursInput.value?.focus()
    }

    const beforeInputHandler = (e: Event & { data?: string }) => {
      if (e.data && !e.data.match(/^[0-9]+$/g)) {
        e.preventDefault()
      }
    }

    const inputHandler = (e: Event & { data?: string }, isForMinutes?: boolean) => {
      const el: HTMLInputElement = e.target as HTMLInputElement
      const val: string | null = el.value

      const maxVal: number = isForMinutes ? 59 : 23
      const timestamp: Moment = moment(props.modelValue ?? { m: 0 })
      const timestampAction: keyof Moment = isForMinutes ? 'minute' : 'hour'

      if (isFirstFocus) {
        timestamp[timestampAction](Number(e.data))

        toggleIsFirstFocus(false)
      } else {
        const lastLetter: string = val.slice(1, -1)
        let time = Number(`${lastLetter}${e.data}`)

        if (time === (maxVal + 1)) {
          time = 0
        } else if (time > maxVal) {
          time = maxVal
        }

        timestamp[timestampAction](time)

        if (!isForMinutes && minutesInput.value) {
          minutesInput.value.focus()
        } else if (isForMinutes && hoursInput.value) {
          hoursInput.value.focus()
        }
      }

      if (timestamp.isValid() && props.onValueChange) {
        props.onValueChange(timestamp)
      }
    }

    const mousewheelHandler = (e: WheelEvent, isForMinutes?: boolean) => {
      e.preventDefault()

      if (props.isDisabled) return

      const maxVal: number = isForMinutes ? 59 : 23
      const incrementVal: number = isForMinutes ? 10 : 1
      const timestamp: Moment = moment(props.modelValue ?? { m: 0 })
      const timestampAction: keyof Moment = isForMinutes ? 'minute' : 'hour'
      let time: number = timestamp[timestampAction]()

      if (e.deltaY > 0) {
        time += incrementVal
      } else {
        time -= incrementVal
      }

      if (time === (maxVal + 1)) {
        time = 0
      } else if ((time > maxVal) || (time <= 0)) {
        time = maxVal
      }

      timestamp[timestampAction](time)

      if (timestamp.isValid() && props.onValueChange) {
        props.onValueChange(timestamp)
      }
    }

    return () => (
      <div
        class={`ark-ui-time-picker ${props.isDisabled ? 'disabled' : ''} ${props.isWithCopy ? 'withCopy' : ''} ${props.errors.length ? 'invalid' : ''}`}
        onClick={clickHandler}
      >

        { props.isShowLabel ? <span class="ark-ui-time-picker-label">{ props.label }</span> : '' }

        <div class="ark-ui-time-picker-input">
          <div>
            <input
              class="ark-ui-time-picker-input-element"
              ref={hoursInput}

              onInput={inputHandler}
              onBeforeinput={beforeInputHandler}
              onFocusout={() => toggleIsFirstFocus(true)}
              onWheel={mousewheelHandler}

              type="text"
              value={props.modelValue?.format('HH') ?? ''}
              placeholder={`${props.placeholder}:`}
              disabled={props.isDisabled}
            />

            <span
              class="ark-ui-time-picker-input-dots"
              style={`${props.modelValue?.format('HH') ? 'color: #27282E;' : ''} ${props.isDisabled ? 'color: #D3D5E5;' : ''}`}
            >
                :
            </span>

            <input
              class="ark-ui-time-picker-input-element"
              ref={minutesInput}

              onClick={(e) => e.stopPropagation()}
              onInput={(e) => inputHandler(e, true)}
              onBeforeinput={beforeInputHandler}
              onFocusout={() => toggleIsFirstFocus(true)}
              onWheel={(e) => mousewheelHandler(e, true)}

              type="text"
              value={props.modelValue?.format('mm') ?? ''}
              placeholder={props.placeholder}
              disabled={props.isDisabled}
            />
          </div>

          {!props.isDisabled && (
            <>
              {
                props.modelValue === null || props.modelValue.isSame(moment({ m: 0 }))
                  ? <Clock />
                  : (
                    <div style="display: flex" onClick={() => props.onValueChange && props.onValueChange(null)}>
                      <Close />
                    </div>
                  )
              }
            </>
          )}
        </div>

        { !props.isDisabled && props.errors.map((item) => <div class='ark-ui-time-picker-error'>{item}</div>) }
      </div>
    )
  },
})
</script>

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

.ark-ui-time-picker {
  cursor: pointer;

  &-label {
    display: block;
    font-size: 12px;
    line-height: 16px;
    color: $placeholder-grey;
    margin-bottom: 8px;
  }

  &-input {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    height: 40px;
    box-sizing: border-box;
    font-size: 14px;
    white-space: nowrap;
    color: #27282E;
    border-radius: 4px;
    border: 1px solid #D3D5E5;
    padding: 10px 12px 10px 16px;

    &-element {
      width: 16px;
      height: 15px;
      font-size: 14px;
      line-height: 16px;
      font-weight: 400;
      color: #27282E;
      caret-color: transparent;
      border: none;
      outline: none;
      background-color: transparent;
      padding: 0;

      &::placeholder {
        color: #A3A7B9;
      }

      &:focus {
        background-color: #F0F1F7;
      }
    }

    &-dots {
      color: #A3A7B9;
      font-size: 14px;
      line-height: 16px;
      font-weight: 400;
    }

    &:hover, &:has(.ark-ui-time-picker-input-element:focus) {
      border-color: #A3A7B9;

      .ark-ui-time-picker-icon path {
        fill: #585B69;
      }
    }
  }

  &-error {
    font-size: 12px;
    color: $error-color;

    margin-top: 4px;
  }

  &.invalid {
    .ark-ui-time-picker-input {
      border-color: $error-color;
    }
  }

  &.withCopy {
    cursor: copy !important;
  }

  &.disabled {
    cursor: default;

    .ark-ui-time-picker {
      &-input {
        border-color: #F6F6FA !important;
        background-color: #F6F6FA;

        color: #585B69;

        &-element, &-element::placeholder {
          color: #D3D5E5;
        }
      }

      &-label {
        color: #585B69;
      }
    }
  }
}
</style>
