import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
import { QPopupProxy, date } from 'quasar';
import debounce from 'lodash/debounce';
import omit from 'lodash/omit';
import {
  convertDateFromBackendFormat,
  convertDateToBackendFormat,
} from '@utils/format-date';
import { DateFormat } from '@constants/utils/format-date';

@Component
export default class DateInput extends Vue {
  @Prop({ default: 'date' }) private emitFormat!:
    | 'date'
    | 'timestamp'
    | 'backend'
    | string;

  @Prop({ default: '' }) private value!: string | Date | number;
  @Prop({ default: '' }) private min!: string | Date | number;
  @Prop({ default: '' }) private max!: string | Date | number;
  // @Prop() private options: QDate['options'];

  private get props() {
    return Object.assign(
      {
        dense: true,
        borderless: true,
        hideBottomSpace: true,
      },
      this.$attrs
    );
  }

  private get slots() {
    return omit(this.$scopedSlots, 'append');
  }

  protected get innerMin() {
    return this.min ? this.getOptionValue(this.min) : NaN;
  }

  protected get innerMax() {
    return this.max ? this.getOptionValue(this.max) : NaN;
  }

  protected options(date: string) {
    return !(date > this.innerMax || date < this.innerMin);
  }

  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 'backend':
        return convertDateToBackendFormat(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 'backend':
        return convertDateFromBackendFormat(val, this.dateMask);
      case this.dateMask:
        return val as string;
      default:
        return date.formatDate(
          date.extractDate(val as string, this.emitFormat),
          this.dateMask
        );
    }
  }

  private getOptionValue(val: string | Date | number): string {
    const mask = DateFormat.yearMonthDay;
    switch (this.emitFormat) {
      case 'date':
      case 'timestamp':
        return date.formatDate(val, mask);
      case 'backend':
        return convertDateFromBackendFormat(val, mask);
      case this.dateMask:
        return val as string;
      default:
        return date.formatDate(
          date.extractDate(val as string, this.emitFormat),
          mask
        );
    }
  }

  @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
    );
  }
}
