import { createElementVNode as _createElementVNode, mergeProps as _mergeProps, createVNode as _createVNode } from "vue";
// Styles
import "./VTimePicker.css";

// Components
import { VTimePickerClock } from "./VTimePickerClock.js";
import { VTimePickerControls } from "./VTimePickerControls.js";
import { makeVPickerProps, VPicker } from "../../labs/VPicker/VPicker.js"; // Composables
import { makeDensityProps, useDensity } from "../../composables/density.js";
import { useLocale } from "../../composables/locale.js";
import { useProxiedModel } from "../../composables/proxiedModel.js"; // Utilities
import { computed, onMounted, ref, toRef, watch } from 'vue';
import { makeTimeValidationProps, useTimeValidation } from "./useTimeValidation.js";
import { convert12to24, convert24to12, pad } from "./util.js";
import { genericComponent, omit, propsFactory, useRender } from "../../util/index.js"; // Types
export const makeVTimePickerProps = propsFactory({
  disabled: Boolean,
  format: {
    type: String,
    default: 'ampm'
  },
  viewMode: {
    type: String,
    default: 'hour'
  },
  period: {
    type: String,
    default: 'am',
    validator: v => ['am', 'pm'].includes(v)
  },
  modelValue: null,
  readonly: Boolean,
  scrollable: Boolean,
  useSeconds: Boolean,
  variant: {
    type: String,
    default: 'dial'
  },
  ...makeTimeValidationProps(),
  ...omit(makeVPickerProps({
    title: '$vuetify.timePicker.title'
  }), ['landscape']),
  ...makeDensityProps()
}, 'VTimePicker');
export const VTimePicker = genericComponent()({
  name: 'VTimePicker',
  props: makeVTimePickerProps(),
  emits: {
    'update:hour': val => true,
    'update:minute': val => true,
    'update:period': val => true,
    'update:second': val => true,
    'update:modelValue': val => true,
    'update:viewMode': val => true
  },
  setup(props, {
    emit,
    slots
  }) {
    const {
      t
    } = useLocale();
    const {
      densityClasses
    } = useDensity(props);
    const inputHour = ref(null);
    const inputMinute = ref(null);
    const inputSecond = ref(null);
    const lazyInputHour = ref(null);
    const lazyInputMinute = ref(null);
    const lazyInputSecond = ref(null);
    const period = useProxiedModel(props, 'period', 'am');
    const viewMode = useProxiedModel(props, 'viewMode', 'hour');
    const controlsRef = ref(null);
    const clockRef = ref(null);
    const isAmPm = computed(() => {
      return props.format === 'ampm';
    });
    const {
      isAllowedHour,
      isAllowedMinute,
      isAllowedSecond
    } = useTimeValidation(props);
    const shouldClear = toRef(() => {
      return props.modelValue !== null && inputHour.value === null && inputMinute.value === null && (!props.useSeconds || inputSecond.value === null);
    });
    function emitValue() {
      const value = genValue();
      if (value !== null && value !== props.modelValue) {
        emit('update:modelValue', value);
      }
      if (shouldClear.value) {
        emit('update:modelValue', null);
      }
    }
    watch(inputHour, emitValue);
    watch(inputMinute, emitValue);
    watch(inputSecond, emitValue);
    watch(period, (newPeriod, oldPeriod) => {
      if (inputHour.value == null || newPeriod === oldPeriod) return;
      if (newPeriod === 'pm' && inputHour.value < 12) {
        inputHour.value = inputHour.value + 12;
      } else if (newPeriod === 'am' && inputHour.value >= 12) {
        inputHour.value = inputHour.value - 12;
      }
    });
    watch(() => props.modelValue, val => setInputData(val));
    watch(() => props.useSeconds, (val, old) => {
      if (old && !val && viewMode.value === 'second') {
        viewMode.value = 'minute';
      }
      if (!val && inputSecond.value !== null) {
        inputSecond.value = null;
      }
    });
    onMounted(() => {
      setInputData(props.modelValue);
    });
    function genValue() {
      if (inputHour.value != null && inputMinute.value != null && (!props.useSeconds || inputSecond.value != null)) {
        return `${pad(inputHour.value)}:${pad(inputMinute.value)}` + (props.useSeconds ? `:${pad(inputSecond.value)}` : '');
      }
      return null;
    }
    function setInputData(value) {
      if (value == null || value === '') {
        inputHour.value = null;
        inputMinute.value = null;
        inputSecond.value = null;
      } else if (value instanceof Date) {
        inputHour.value = value.getHours();
        inputMinute.value = value.getMinutes();
        inputSecond.value = value.getSeconds();
      } else {
        const [hour,, minute,, second, period] = value.trim().toLowerCase().match(/^(\d+):(\d+)(:(\d+))?([ap]m)?$/) || new Array(6);
        inputHour.value = period ? convert12to24(parseInt(hour, 10), period) : parseInt(hour, 10);
        inputMinute.value = parseInt(minute, 10);
        inputSecond.value = parseInt(second || 0, 10);
      }
      period.value = inputHour.value == null || inputHour.value < 12 ? 'am' : 'pm';
    }
    function onInput(value) {
      if (viewMode.value === 'hour') {
        inputHour.value = isAmPm.value ? convert12to24(value, period.value) : value;
      } else if (viewMode.value === 'minute') {
        inputMinute.value = value;
      } else {
        inputSecond.value = value;
      }
    }
    function onChange(value) {
      switch (viewMode.value || 'hour') {
        case 'hour':
          emit('update:hour', value);
          break;
        case 'minute':
          emit('update:minute', value);
          break;
        case 'second':
          emit('update:second', value);
          break;
        default:
          break;
      }
      const emitChange = inputHour.value !== null && inputMinute.value !== null && (props.useSeconds ? inputSecond.value !== null : true);
      if (viewMode.value === 'hour') {
        viewMode.value = 'minute';
      } else if (props.useSeconds && viewMode.value === 'minute') {
        viewMode.value = 'second';
      }
      if (inputHour.value === lazyInputHour.value && inputMinute.value === lazyInputMinute.value && (!props.useSeconds || inputSecond.value === lazyInputSecond.value)) return;
      const time = genValue();
      if (time === null) return;
      lazyInputHour.value = inputHour.value;
      lazyInputMinute.value = inputMinute.value;
      props.useSeconds && (lazyInputSecond.value = inputSecond.value);
      emitChange && emitValue();
    }
    useRender(() => {
      const pickerProps = omit(VPicker.filterProps(props), ['hideHeader']);
      const timePickerControlsProps = VTimePickerControls.filterProps(props);
      const timePickerClockProps = VTimePickerClock.filterProps(omit(props, ['format', 'modelValue', 'min', 'max']));
      const clockValidation = viewMode.value === 'hour' ? isAllowedHour.value : viewMode.value === 'minute' ? v => isAllowedMinute.value(inputHour.value, v) : v => isAllowedSecond.value(inputHour.value, inputMinute.value, v);
      return _createVNode(VPicker, _mergeProps(pickerProps, {
        "color": undefined,
        "class": ['v-time-picker', `v-time-picker--variant-${props.variant}`, props.class, densityClasses.value],
        "hideHeader": props.hideHeader && props.variant !== 'input',
        "style": props.style
      }), {
        title: () => slots.title?.() ?? _createElementVNode("div", {
          "class": "v-time-picker__title"
        }, [t(props.title)]),
        header: () => _createVNode(VTimePickerControls, _mergeProps(timePickerControlsProps, {
          "ampm": isAmPm.value,
          "hour": inputHour.value,
          "minute": inputMinute.value,
          "period": period.value,
          "second": inputSecond.value,
          "viewMode": viewMode.value,
          "inputHints": props.variant === 'input',
          "onUpdate:hour": val => inputHour.value = val,
          "onUpdate:minute": val => inputMinute.value = val,
          "onUpdate:second": val => inputSecond.value = val,
          "onUpdate:period": val => period.value = val,
          "onUpdate:viewMode": value => viewMode.value = value,
          "ref": controlsRef
        }), null),
        default: () => _createVNode(VTimePickerClock, _mergeProps(timePickerClockProps, {
          "allowedValues": clockValidation,
          "double": viewMode.value === 'hour' && !isAmPm.value,
          "format": viewMode.value === 'hour' ? isAmPm.value ? convert24to12 : val => val : val => pad(val, 2),
          "max": viewMode.value === 'hour' ? isAmPm.value && period.value === 'am' ? 11 : 23 : 59,
          "min": viewMode.value === 'hour' && isAmPm.value && period.value === 'pm' ? 12 : 0,
          "size": 20,
          "step": viewMode.value === 'hour' ? 1 : 5,
          "modelValue": viewMode.value === 'hour' ? inputHour.value : viewMode.value === 'minute' ? inputMinute.value : inputSecond.value,
          "onChange": onChange,
          "onInput": onInput,
          "ref": clockRef
        }), null),
        actions: slots.actions
      });
    });
  }
});
//# sourceMappingURL=VTimePicker.js.map