<template>
  <view :class="calendarClass" :style="calendarStyle">
    <view :class="bem.e('header')">
      <view v-if="!severalMonths" :class="bem.e('toolbar')">
        <view :class="bem.e('toolbar-inner')">
          <sar-button
            type="pale-text"
            theme="body"
            :disabled="
              toMonthNumber(innerCurrentDate) <= toMonthNumber(minDate)
            "
            @click="onPrevMonthClick"
          >
            <sar-icon name="left" size="32rpx" />
          </sar-button>
          <sar-button type="pale-text" theme="body" @click="onMonthClick">
            {{
              t('monthTitle', {
                year: innerCurrentDate.getFullYear(),
                month: String(innerCurrentDate.getMonth() + 1).padStart(2, '0'),
              })
            }}
          </sar-button>
          <sar-button
            type="pale-text"
            theme="body"
            :disabled="
              toMonthNumber(innerCurrentDate) >= toMonthNumber(maxDate)
            "
            @click="onNextMonthClick"
          >
            <sar-icon name="right" size="32rpx" />
          </sar-button>
        </view>
      </view>
      <view :class="bem.e('week')">
        <view v-for="(item, i) in weeks" :key="i" :class="bem.e('week-item')">
          {{ t(`weeks.${item}`) }}
        </view>
      </view>
    </view>
    <scroll-view :scroll-y="severalMonths" :class="bem.e('body')">
      <sar-calendar-month
        v-for="(month, i) in months"
        :key="i"
        :year="month[0]"
        :month="month[1]"
        :type="type"
        :min-date="minDate"
        :max-date="maxDate"
        :current-dates="currentDates"
        :formatter="formatter"
        :disabled-date="disabledDate"
        :today-number="todayNumber"
        :week-starts-on="weekStartsOn"
        :several-months="severalMonths"
        :t="t"
        :bem="bem"
        @day-click="handleDayClick"
      />
    </scroll-view>
  </view>

  <sar-popout
    v-if="!severalMonths"
    v-model:visible="pickerVisible"
    type="compact"
    @confirm="onPickerConfirm"
  >
    <sar-datetime-picker
      type="yM"
      v-model="pickerValue"
      :min="minDate"
      :max="maxDate"
    />
  </sar-popout>
</template>

<script lang="ts">
import { defineComponent as _defineComponent } from "vue";
import { computed, ref, watch } from "vue";
import {
  classNames,
  stringifyStyle,
  createBem,
  minmaxDate,
  toDateNumber,
  toMonthNumber,
  getPrevMonthDate,
  getNextMonthDate,
  toArray
} from "../utils";
import {
  calendarProps,
  getMaxDate,
  getMinDate,
  sortDates,
  weeksIndex
} from "./common";
import SarButton from "../button/button.vue";
import SarIcon from "../icon/icon.vue";
import { useTranslate } from "../locale";
import SarCalendarMonth from "../calendar-month/calendar-month.vue";
import SarPopout from "../popout/popout.vue";
import SarDatetimePicker from "../datetime-picker/datetime-picker.vue";
const __default__ = {
  options: {
    virtualHost: true,
    styleIsolation: "shared"
  }
};
export default /* @__PURE__ */ _defineComponent({
  ...__default__,
  __name: "calendar",
  props: calendarProps,
  emits: ["update:model-value"],
  setup(__props, { expose: __expose, emit: __emit }) {
    __expose();
    const props = __props;
    const emit = __emit;
    const bem = createBem("calendar");
    const { t } = useTranslate("calendar");
    const minDate = computed(() => {
      return props.min || getMinDate(props.severalMonths);
    });
    const maxDate = computed(() => {
      const maxDate2 = props.max || getMaxDate(props.severalMonths);
      return maxDate2.getTime() < minDate.value.getTime() ? new Date(minDate.value) : maxDate2;
    });
    const innerValue = ref(
      props.modelValue ?? (props.type === "single" ? void 0 : [])
    );
    watch(
      () => props.modelValue,
      () => {
        if (innerValue.value !== props.modelValue) {
          innerValue.value = props.modelValue ?? (props.type === "single" ? void 0 : []);
        }
      }
    );
    const getInitialCurrentDate = () => {
      let date = /* @__PURE__ */ new Date();
      const value = toArray(props.modelValue)[0];
      if (value) {
        date = value;
      }
      if (props.currentDate) {
        date = props.currentDate;
      }
      return minmaxDate(date, minDate.value, maxDate.value);
    };
    const innerCurrentDate = ref(getInitialCurrentDate());
    watch(
      () => props.currentDate,
      () => {
        innerCurrentDate.value = minmaxDate(
          props.currentDate || /* @__PURE__ */ new Date(),
          minDate.value,
          maxDate.value
        );
      }
    );
    watch(innerValue, () => {
      const onlyOneDate = Array.isArray(innerValue.value) ? innerValue.value.length === 1 ? innerValue.value[0] : void 0 : innerValue.value;
      if (onlyOneDate && toMonthNumber(onlyOneDate) !== toMonthNumber(innerCurrentDate.value)) {
        innerCurrentDate.value = onlyOneDate;
      }
    });
    const startDate = ref(
      props.type === "range" && Array.isArray(innerValue.value) && innerValue.value.length === 1 ? innerValue.value[0] : void 0
    );
    const onPrevMonthClick = () => {
      innerCurrentDate.value = getPrevMonthDate(innerCurrentDate.value);
    };
    const onNextMonthClick = () => {
      innerCurrentDate.value = getNextMonthDate(innerCurrentDate.value);
    };
    const pickerVisible = ref(false);
    const pickerValue = ref(innerCurrentDate.value);
    const onMonthClick = () => {
      pickerValue.value = innerCurrentDate.value;
      pickerVisible.value = true;
    };
    const onPickerConfirm = () => {
      if (toMonthNumber(innerCurrentDate.value) !== toMonthNumber(pickerValue.value)) {
        innerCurrentDate.value = pickerValue.value;
      }
    };
    const weeks = computed(() => {
      return weeksIndex.slice(props.weekStartsOn).concat(weeksIndex.slice(0, props.weekStartsOn));
    });
    const months = computed(() => {
      if (!props.severalMonths) {
        return [
          [innerCurrentDate.value.getFullYear(), innerCurrentDate.value.getMonth()]
        ];
      }
      const minYear = minDate.value.getFullYear();
      const minMonth = minDate.value.getMonth();
      const maxYear = maxDate.value.getFullYear();
      const maxMonth = maxDate.value.getMonth();
      const months2 = (maxYear - minYear) * 12 + (maxMonth - minMonth + 1);
      return Array(months2).fill(0).map((_, i) => {
        return [minYear + Math.floor((minMonth + i) / 12), (minMonth + i) % 12];
      });
    });
    const todayNumber = toDateNumber(/* @__PURE__ */ new Date());
    const currentDates = computed(() => {
      let dates;
      if (props.type === "range" && startDate.value) {
        dates = [startDate.value];
      } else {
        if (Array.isArray(innerValue.value)) {
          dates = innerValue.value;
        } else if (innerValue.value) {
          dates = [innerValue.value];
        } else {
          dates = [];
        }
      }
      return dates;
    });
    const handleDayClick = (date) => {
      let nextValue;
      if (props.type === "single") {
        nextValue = date;
      } else if (props.type === "multiple") {
        if (Array.isArray(innerValue.value)) {
          if (innerValue.value.some((d) => toDateNumber(d) === toDateNumber(date))) {
            nextValue = innerValue.value.filter(
              (d) => toDateNumber(d) !== toDateNumber(date)
            );
          } else {
            if (innerValue.value.length >= props.maxDays) {
              props.overMaxDays?.();
              return;
            }
            nextValue = sortDates(innerValue.value.concat(date));
          }
        }
      } else if (props.type === "range") {
        if (startDate.value) {
          const startDays = toDateNumber(startDate.value);
          const endDays = toDateNumber(date);
          if (!props.allowSameDay && startDays === endDays) {
            return;
          }
          const startAgain = endDays < startDays;
          if (startAgain) {
            startDate.value = date;
            return;
          }
          let endDate = date;
          if (endDays - startDays + 1 > props.maxDays) {
            props.overMaxDays?.();
            endDate = new Date(startDate.value);
            endDate.setDate(endDate.getDate() + (props.maxDays - 1));
          }
          nextValue = [startDate.value, endDate];
        } else {
          nextValue = [];
        }
        startDate.value = startDate.value ? void 0 : date;
      }
      if (nextValue !== void 0) {
        innerValue.value = nextValue;
        emit("update:model-value", nextValue);
      }
    };
    const calendarClass = computed(() => {
      return classNames(
        bem.b(),
        bem.m("several", props.severalMonths),
        props.rootClass
      );
    });
    const calendarStyle = computed(() => {
      return stringifyStyle(props.rootStyle);
    });
    const __returned__ = { props, emit, bem, t, minDate, maxDate, innerValue, getInitialCurrentDate, innerCurrentDate, startDate, onPrevMonthClick, onNextMonthClick, pickerVisible, pickerValue, onMonthClick, onPickerConfirm, weeks, months, todayNumber, currentDates, handleDayClick, calendarClass, calendarStyle, get toMonthNumber() {
      return toMonthNumber;
    }, SarButton, SarIcon, SarCalendarMonth, SarPopout, SarDatetimePicker };
    return __returned__;
  }
});
</script>

<style lang="scss">
@use './index.scss';
</style>