<template>
  <q-input
    v-model="innerValue"
    :mask="inputMask"
    :rules="[dateRule]"
    v-bind="$attrs"
    filled
    dense
    :label="label"
    borderless
    hide-bottom-space
    class="x--small-input x-date__input"
  >
    <template #append>
      <q-icon name="event" class="cursor-pointer">
        <q-popup-proxy
          ref="qDateProxy"
          transition-show="scale"
          transition-hide="scale"
        >
          <div class="x-date__calendar" @click="hideClearButton">
            <q-date
              v-model="innerValue"
              minimal
              :options="options"
              :mask="dateMask"
              @input="closePopup"
              :default-view="defaultView"
            />
            <q-btn
              v-show="value"
              v-t="'base.clear'"
              class="x-date__clear"
              color="primary"
              no-caps
              :class="{ 'x-date__clear--hidden': clearButtonHidden }"
              @click.stop="closePopup((innerValue = ''))"
            />
          </div>
        </q-popup-proxy>
      </q-icon>
    </template>
  </q-input>
</template>

<script lang="ts">
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
import { QPopupProxy, QDate, date } from 'quasar';
import { debounce } from 'lodash';
import { QDate as QDateType } from 'quasar/dist/types';

@Component
export default class XDateInput extends Vue {
  @Prop({ default: 'date' }) private emitFormat!: 'date' | 'timestamp' | string;
  @Prop({ default: '' }) private value!: string | Date | number;
  @Prop() private options: QDate['options'];
  @Prop() private label: string;
  @Prop({ default: 'Calendar' }) private defaultView: QDateType["defaultView"];

  private innerValue = '';

  private get inputMask(): string {
    return this.$store.getters['i18N/localeMask'].input;
  }

  private get dateMask(): string {
    return this.$store.getters['i18N/localeMask'].date;
  }

  private getEmitValue(val: string) {
    switch (this.emitFormat) {
      case 'date':
        return date.extractDate(val, this.dateMask);
      case 'timestamp':
        return +date.extractDate(val, this.dateMask);
      case this.dateMask:
        return val;
      default:
        return date.formatDate(
          date.extractDate(val, this.dateMask),
          this.emitFormat
        );
    }
  }

  private getInnerValue(val: string | Date | number): string {
    switch (this.emitFormat) {
      case 'date':
      case 'timestamp':
        return date.formatDate(val, this.dateMask);
      case this.dateMask:
        return val as string;
      default:
        return date.formatDate(
          date.extractDate(val as string, this.emitFormat),
          this.dateMask
        );
    }
  }

  @Watch('value', { immediate: true })
  private setInnerValue(val: string | Date | number) {
    this.innerValue = this.getInnerValue(val);
  }

  private clearButtonHidden = false;

  private hideClearButton(e: Event) {
    try {
      // fixme избавиться от try catch
      const { arrowLeft, arrowRight } = this.$q.iconSet.datetime;
      const arrow = (e.target as any).firstChild.data.trim();

      if (arrow !== arrowLeft && arrow !== arrowRight) return false;
    } catch (e) {
      return false;
    }

    this.clearButtonHidden = true;
    this.showClearButton();
  }

  private showClearButton!: () => void;

  private closePopup() {
    (this.$refs.qDateProxy as QPopupProxy).hide();
  }

  @Watch('innerValue')
  private innerValueChanged(val: string) {
    if (!val && !this.value) return; // todo разобраться откуда лишние вызовы при установке пустого значения

    this.$emit('input', val ? this.getEmitValue(val) : '');
  }

  private created() {
    this.showClearButton = debounce(
      () => (this.clearButtonHidden = false),
      200
    );
  }

  private dateRule() {
    return true; // todo
  }
}
</script>

<style lang="sass">
.x-date
  &__input
    width: 10.5em

    .q-field__control
      padding: 0 12px !important

  &__calendar
    position: relative

  &__clear
    opacity: 1
    position: absolute
    right: 24px
    bottom: 20px
    padding-right: 8px
    padding-left: 8px
    box-shadow: none
    transition: opacity .2s

    &--hidden
      opacity: 0
</style>
