<template>
  <div
    ref="pickerWrap"
    :style="setMaxWidth"
    :class="{ 'vc-datetime-picker--error': error }"
    class="vc-datetime-picker"
  >
    <div class="vc-datetime-picker__label mb-2">
      <label class="vc-datetime-picker__label-wrapper flex items-center">
        <span
          v-if="labelIcon"
          class="vc-datetime-picker__label-wrapper--left-item"
        >
          <i
            :class="labelIcon"
            class="icon-lg vc-datetime-picker__label-wrapper--left-item-icon text-icons"
          />
        </span>
        <span
          v-if="label"
          class="vc-datetime-picker__label-wrapper-label"
        >
          {{ label }}
          <span
            v-if="required"
            class="vc-datetime-picker__label-wrapper-label__required-icon"
          >*</span>
        </span>
        <VcPopover
          v-if="infoText || $slots['info-text']"
          :popover-width="infoTooltipWidth"
          arrow-position="bottom-center"
        >
          <template #reference>
            <span class="vc-input__label-info px-1 flex items-center">
              <i class="vc-icon-info icon-base" />
            </span>
          </template>
          <div
            class="label-info-text p-2 text-xs"
          >
            <slot name="info-text">
              {{ infoText }}
            </slot>
          </div>
        </VcPopover>
      </label>
    </div>
    <Datepicker
      ref="picker"
      v-model="dateModel"
      :uid="id"
      :auto-apply="autoApply"
      :data-test="dataTestName"
      :disabled="disabled"
      :enable-time-picker="enableTimePicker"
      :enable-seconds="enableSeconds"
      :inline="inline"
      :format="format"
      :locale="locale"
      :multi-calendars="range"
      :multi-calendars-solo="range"
      :placeholder="placeholder"
      :preset-ranges="presetRanges"
      :range="range"
      :transitions="false"
      :utc="utc"
      :input-class-name="inputClasses"
      calendar-cell-class-name="dp-custom-cell"
      :class="['vc-datetime-input', {'hide-border': hideBorder}]"
      :min-date="minDate"
      :max-date="maxDate"
      :min-time="minTime"
      :max-time="maxTime"
      @internal-model-change="onInternalModelChange"
      @open="onOpen"
      @closed="onClosed"
      @focus="onFocus"
      @blur="onBlur"
    >
      <template #input-icon>
        <span class="h-full flex items-center justify-center w-6">
          <i
            :class="prefixClasses"
            :style="prefixStyle"
          />
        </span>
      </template>
      <template #clear-icon="{ clear }">
        <span class="h-full w-6 flex items-center justify-center">
          <i
            class="vc-icon-close icon-xxs hover:text-active-elements"
            @click="clear"
          />
        </span>
      </template>
      <template #clock-icon>
        <i
          class="vc-icon-clock icon-lg hover:text-active-elements"
        />
      </template>
      <template #calendar-icon>
        <i
          class="vc-icon-schedule-calendar icon-lg hover:text-active-elements"
        />
      </template>
      <template
        v-if="!autoApply"
        #action-select
      >
        <VcButton
          type="default"
          size="middle"
          icon="vc-icon-Save"
          :disabled="selectDateButtonDisabled"
          @click="selectDate"
        >
          {{ applyButtonText }}
        </VcButton>
      </template>
    </Datepicker>
    <div
      v-if="!dynamicErrorSpace || (dynamicErrorSpace && displayError)"
      class="vc-datetime-picker__error-wrapper"
    >
      <span class="vc-datetime-picker__error-wrapper--text">
        {{ displayError }}
      </span>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent, PropType } from 'vue'
import {
  VcDatetimeRangePickerModelType,
  VcDatetimeRangePickerType,
  VcPresetRangesType,
  VcDatetimeRangePickerTimeType
} from './VcDatetimeRangePicker.types'
import type {
  InternalModuleValue,
  ITimeValue
} from '@vuepic/vue-datepicker/src/VueDatePicker/interfaces'
import Datepicker from '@vuepic/vue-datepicker'
import isValidTime from '@/utils/isValidTime'
import inputMixin from '@/mixins/input.mixin'
import VcButton from '@/components/VcButton/VcButton.vue'
import { convertToUnit } from '@/utils/helpers'

const CLASS_FOR_COLOR = 'vc-input-color--'

export default defineComponent({
  name: 'VcDatetimeRangePicker',
  components: {
    VcButton,
    Datepicker
  },
  mixins: [inputMixin],
  props: {
    modelValue: {
      type: [Date, String, Array, Object] as PropType<VcDatetimeRangePickerModelType>,
      default: null
    },
    maxWidth: {
      type: [String, Number],
      default: '100%'
    },
    presetRanges: {
      type: Array as PropType<VcPresetRangesType>,
      default: () => []
    },
    placeholder: {
      type: String,
      default: ''
    },
    range: {
      type: Boolean,
      default: false
    },
    enableTimePicker: {
      type: Boolean,
      default: false
    },
    enableSeconds: {
      type: Boolean,
      default: false
    },
    inline: {
      type: Boolean,
      default: false
    },
    utc: {
      type: Boolean,
      default: false
    },
    autoApply: {
      type: Boolean,
      default: false
    },
    format: {
      type: String,
      default: undefined
    },
    applyButton: {
      type: String,
      default: ''
    },
    locale: {
      type: String,
      default: 'en-US'
    },
    minDate: {
      type: [Date, String],
      default: null
    },
    maxDate: {
      type: [Date, String],
      default: null
    },
    minTime: {
      type: Object as PropType<VcDatetimeRangePickerTimeType>,
      default: null
    },
    maxTime: {
      type: Object as PropType<VcDatetimeRangePickerTimeType>,
      default: null
    },
    weekStart: {
      type: [Number, String],
      default: 1
    },
    teleport: {
      type: String,
      default: 'body'
    },
    hideBorder: {
      type: Boolean,
      default: false
    }
  },
  emits: ['input', 'update:modelValue', 'open', 'closed', 'focus', 'blur'],
  data () {
    return {
      defaultPrefixIcon: 'vc-icon-schedule-calendar',
      internalModelValue: null as InternalModuleValue,
      localError: ''
    }
  },
  computed: {
    selectDateButtonDisabled (): boolean {
      return !this.isTimeValid || this.internalModelValue === null
    },
    isTimeValid (): boolean {
      if (!this.enableTimePicker) return true

      return isValidTime(this.internalModelValue, this.maxTime as ITimeValue, this.minTime as ITimeValue)
    },
    displayError (): string {
      return this.error || this.localError
    },
    inputClasses (): string {
      return this.color ? (CLASS_FOR_COLOR + this.color) : ''
    },
    setMaxWidth (): string {
      const size = convertToUnit(this.maxWidth) as string | undefined
      return `max-width: ${size}`
    },
    dateModel: {
      get (): VcDatetimeRangePickerModelType {
        return this.modelValue
      },
      set (val: VcDatetimeRangePickerModelType) {
        if (this.disabled) {
          return
        }
        this.$emit('input', val)
        this.$emit('update:modelValue', val)
      }
    },
    applyButtonText () {
      return this.applyButton ? this.applyButton : this.$tVU.t('general.apply')
    }
  },
  watch: {
    isTimeValid: {
      handler (val: boolean) {
        this.localError = val ? '' : this.$tVU.t('date.picker.time.is.invalid')
      },
      immediate: true
    }
  },
  methods: {
    onInternalModelChange (val: InternalModuleValue) {
      this.internalModelValue = val
    },
    selectDate (): void {
      const picker = this.$refs.picker as VcDatetimeRangePickerType
      picker.selectDate()
    },
    onOpen (): void {
      this.$emit('open')
    },
    onClosed (): void {
      this.$emit('closed')
    },
    onFocus (): void {
      this.$emit('focus')
    },
    onBlur (): void {
      this.$emit('blur')
    }
  }
})
</script>

<style lang="scss">
$dp__font_size: 0.875rem;
$dp__input_padding: 0 1.5rem;
$dp__input_icon_padding: 1.5rem;
$dp__border_radius: 6px;
$dp__button_height: 2rem;
$dp__month_year_row_height: 2rem;
$dp__cell_size: 2rem;
$dp__time_font_size: 1.5rem;

@import '@vuepic/vue-datepicker/src/VueDatePicker/style/main.scss';

.dp__theme_light {
  --dp-hover-color: var(--active-elements-bg--focus);
  --dp-primary-color: var(--primary-actions);
}
.vc-datetime-picker {
  &__label {
    &-wrapper {
      @apply flex text-sm text-default-text font-normal;
      &--left-item {
        @apply inline-flex;
        &-icon {
          @apply mr-2 leading-none;
          [dir=rtl] & {
            @apply mr-0 ml-2;
          }
        }
      }
      &-label {
        @apply text-sm text-default-text font-normal;
        &__required-icon {
          @apply text-primary-actions;
        }
      }
    }
  }
  &__error-wrapper {
    @apply relative w-full text-xs leading-normal;
    &--text {
      @apply inline-flex flex-wrap text-destructive-actions text-xs left-0 top-0 w-full overflow-hidden overflow-ellipsis whitespace-nowrap;
    }
  }
}
.dp__input {
  @apply h-8 border-field-borders;
  &:hover:not(:disabled):not(.dp__input_focus) {
    @apply shadow-focus-outer;
  }
  &.vc-input-color--active {
    &:hover:not(:disabled):not(.dp__input_focus) {
      @apply shadow-focus-outer;
    }
  }
  &.vc-input-color--primary {
    &:hover:not(:disabled):not(.dp__input_focus) {
      @apply shadow-focus-outer-primary;
    }
  }
  &.vc-input-color--secondary {
    &:hover:not(:disabled):not(.dp__input_focus) {
      @apply shadow-focus-outer-secondary;
    }
  }
  &.vc-input-color--destructive {
    &:hover:not(:disabled):not(.dp__input_focus) {
      @apply shadow-focus-outer-destructive;
    }
  }
}
.dp__input_focus, .dp__input.dp__input_focus {
  @apply border-primary-actions--focus;
}
.dp__disabled {
  @apply bg-default-bg;
  &:hover {
    @apply cursor-not-allowed shadow-none;
  }
}
.vc-datetime-picker--error {
  .dp__input {
    @apply border-error;
  }
}

.dp__action_row {
  @apply border-t border-ui-lines;
  border-radius: 0 0 $dp__border_radius $dp__border_radius;
}

.dp__date_hover_start, .dp__date_hover_end, .dp__range_end {
  &:hover {
    border-radius: 50%;
  }
}
.dp__input_icon, .dp__clear_icon {
  @apply h-full;
}
.dp__input_icon {
  .vc-input-icon-color--active {
    @apply text-active-elements;
  }
  .vc-input-icon-color--primary {
    @apply text-primary-actions;
  }
  .vc-input-icon-color--secondary {
    @apply text-secondary-actions;
  }
  .vc-input-icon-color--destructive {
    @apply text-destructive-actions;
  }
}

.dp__inner_nav {
  @apply text-primary-actions;
  &:hover {
    @apply text-primary-actions bg-active-elements-bg--focus;
  }
}
.dp__overlay {
  border-radius: $dp__border_radius;
}

.dp-custom-cell {
  border-radius: 50%;
}
.dp__preset_ranges {
  width: 150px;
}

.hide-border .dp__menu {
  border: none;
}

// RTL styles:
[dir='rtl'] {
  .dp__clear_icon {
    right: auto;
    left: 0;
  }
  .dp__input_icon {
    left: auto;
    right: 0;
  }
  .dp__action_buttons {
    text-align: left;
  }
  .dp__inner_nav {
    transform: rotate(180deg);
  }
  .dp__calendar_next {
    margin-left: 0;
    margin-right: 10px;
  }
  .dp__overlay_row {
    flex-direction: row-reverse;
  }
}
</style>
