<template>
  <q-input
    v-model="dateTime"
    filled
    :readonly="readonly"
    :label="label"
    :placeholder="placeholder"
    :rules="customRules"
  >
    <template #append>
      <q-icon v-if="type == 'date' || type == 'datetime'" name="event" class="cursor-pointer">
        <q-popup-proxy ref="qDateProxy" transition-show="scale" transition-hide="scale">
          <q-date :model-value="getDate()" mask="YYYY-MM-DD" @input="dateChanged">
            <div class="row items-center justify-end">
              <q-btn v-close-popup label="Schließen" color="primary" flat />
            </div>
          </q-date>
        </q-popup-proxy>
      </q-icon>
      <q-icon
        v-if="type == 'time' || type == 'datetime'"
        name="mdi-clock-outline"
        class="cursor-pointer"
      >
        <q-popup-proxy ref="qTimeProxy" transition-show="scale" transition-hide="scale">
          <q-time :model-value="getTime()" mask="HH:mm" @update:modelValue="timeChanged">
            <div class="row items-center justify-end">
              <q-btn v-close-popup label="Schließen" color="primary" flat />
            </div>
          </q-time>
        </q-popup-proxy>
      </q-icon>
    </template>
  </q-input>
</template>

<script lang="ts">
import { computed, defineComponent, ref, PropType } from 'vue';
import { date as q_date } from 'quasar';

export default defineComponent({
  name: 'IsoDateInput',
  props: {
    modelValue: { type: Date, default: new Date() },
    type: {
      type: String,
      default: 'date',
      validator: (value: string) => ['date', 'time', 'datetime'].indexOf(value) !== -1,
    },
    label: { type: String, default: 'Datum' },
    readonly: Boolean,
    rules: {
      type: Array as PropType<unknown[]>,
      default: () => [],
    },
  },
  emits: { input: (date: string) => date.length > 5 },
  setup(props, { emit }) {
    const _date = ref('');
    const _time = ref('');
    const placeholder = computed(() => {
      switch (props.type) {
        case 'date':
          return 'YYYY-MM-DD';
        case 'time':
          return 'HH:mm';
        case 'datetime':
          return 'YYYY-MM-DD HH:mm';
      }
      throw 'Invalid type given';
    });

    const dateTime = computed({
      get() {
        if (typeof props.modelValue == 'object') {
          switch (props.type) {
            case 'date':
              return getDate();
            case 'time':
              return getTime();
            case 'datetime':
              return `${getDate()} ${getTime()}`;
          }
        }
        return props.modelValue;
      },
      set(dateTimeString: string) {
        switch (props.type) {
          case 'date':
            dateChanged(dateTimeString);
            break;
          case 'time':
            timeChanged(dateTimeString);
            break;
          case 'datetime':
            const _dateTime = dateTimeString.split(' ');
            _date.value = _dateTime[0];
            _time.value = _dateTime[1];
            console.log(dateTimeString, _dateTime);
            if (/^\d{4}-\d\d-\d\d \d\d:\d\d$/.test(dateTimeString)) {
              console.log('dateTimeChanged');
              emit('input', new Date(`${_date.value} ${_time.value}`).toISOString());
            } else {
              emit('input', dateTimeString);
            }
        }
      },
    });

    function dateChanged(dateString: string) {
      _date.value = dateString;
      console.log(dateString);

      if (/^\d{4}-\d\d-\d\d$/.test(dateString)) {
        emit('input', new Date(`${_date.value} ${_time.value}`).toISOString());
      } else {
        emit('input', dateString);
      }
    }

    function timeChanged(timeString: string) {
      _time.value = timeString;
      if (_date.value == '') {
        _date.value = q_date.formatDate(new Date(), 'YYYY-MM-DD');
      }
      if (/^\d\d:\d\d$/.test(timeString)) {
        emit('input', new Date(`${_date.value} ${_time.value}`).toISOString());
      } else {
        emit('input', timeString);
      }
    }

    function getDate() {
      if (typeof props.modelValue == 'object') {
        return q_date.formatDate(props.modelValue, 'YYYY-MM-DD');
      }
      return '';
    }
    function getTime() {
      if (typeof props.modelValue == 'object') {
        return q_date.formatDate(props.modelValue, 'HH:mm');
      }
      return '';
    }

    function isDate(val: string) {
      return !val || /^\d{4}-\d\d-\d\d$/.test(val) || 'Datum ist nicht gültig.';
    }

    function isTime(val: string) {
      return !val || /^\d\d:\d\d$/.test(val) || 'Zeit ist nicht gültig.';
    }

    function isDateTime(val: string) {
      return !val || /^\d{4}-\d\d-\d\d \d\d:\d\d$/.test(val) || 'Datum und Zeit ist nicht gültig.';
    }

    const customRules = [
      props.type == 'date' ? isDate : props.type == 'time' ? isTime : isDateTime,
      ...props.rules,
    ];

    return {
      dateTime,
      getDate,
      getTime,
      dateChanged,
      customRules,
      timeChanged,
      placeholder,
    };
  },
});
</script>
