<template>
  <div class="mm-time-picker-panel">
    <ui-time-picker-select
      v-if="hasHour"
      v-model="hour"
      :list="hours"
      :visible="visible"></ui-time-picker-select>
    <ui-time-picker-select
      v-if="hasMin"
      v-model="minute"
      :list="minutes"
      :visible="visible"></ui-time-picker-select>
    <ui-time-picker-select
      v-if="hasSec"
      v-model="second"
      :list="seconds"
      :visible="visible"></ui-time-picker-select>
    <div
      v-if="use12hour"
      class="mm-time-picker-panel-select">
      <ul
        class="mm-time-picker-list">
        <li
          v-for="(item, key) of ['AM', 'PM']"
          :key="key"
          :class="{
            'mm-time-picker-item': true,
            'mm-time-picker-item--active': ampm === item
          }"
          @click="ampm = item">
          {{ item }}
        </li>
      </ul>
    </div>
  </div>
</template>

<script>
import { parseDate } from "../../utils/date"
import Select from "./select"

const rangeNumbers = function(min, max) {
  return Array.from({ length: max - min }).map((_, index) => min + index)
}

export default {
  name: "mm-time-picker-panel",
  components: {
    "ui-time-picker-select": Select,
  },
  props: {
    value: [String, Date],
    use12hour: {
      type: Boolean,
      default: false,
    },
    visible: {
      type: Boolean,
      default: false,
    },
    disabledHours: {
      type: Function,
      default() {
        return false
      },
    },
    disabledMinutes: {
      type: Function,
      default() {
        return false
      },
    },
    disabledSeconds: {
      type: Function,
      default() {
        return false
      },
    },
    format: {
      type: String,
      default: "HH:mm:ss",
    },
  },
  data() {
    return {
      hour: "",
      second: "",
      minute: "",
      ampm: "",
      maxHour: this.use12hour ? 12 : 24,
    }
  },
  computed: {
    hasHour() {
      return this.format.toLowerCase().indexOf("h") !== -1
    },
    hasMin() {
      return this.format.toLowerCase().indexOf("m") !== -1
    },
    hasSec() {
      return this.format.toLowerCase().indexOf("s") !== -1
    },
    hours() {
      return rangeNumbers(0, this.maxHour).map(item => ({
        value: item,
        disabled: this.disabledHours(item),
      }))
    },
    minutes() {
      return rangeNumbers(0, 60).map(item => ({
        value: item,
        disabled: this.disabledMinutes(this.hour, item),
      }))
    },
    seconds() {
      return rangeNumbers(0, 60).map(item => ({
        value: item,
        disabled: this.disabledSeconds(this.hour, this.minute, item),
      }))
    },
    selectedTimeStr() {
      let hour = this.isDisabledItem(this.hours, this.hour)
        ? this.getMinValidNumber(this.hours)
        : this.hour
      let minute = this.isDisabledItem(this.minutes, this.minute)
        ? this.getMinValidNumber(this.minutes)
        : this.minute
      let second = this.isDisabledItem(this.seconds, this.second)
        ? this.getMinValidNumber(this.seconds)
        : this.second

      return `${hour}:${minute}:${second}${this.use12hour ? " " + this.ampm : ""}`
    },
    selectedTime() {
      const timeFormat = this.use12hour ? "hh:mm:ss A" : "HH:mm:ss"
      return this.selectedTimeStr ? parseDate(this.selectedTimeStr, timeFormat) : ""
    },
  },
  watch: {
    value: {
      immediate: true,
      handler(value) {
        let hour = value ? value.getHours() : ""
        let minute = value ? value.getMinutes() : ""
        let second = value ? value.getSeconds() : ""

        this.hour = this.use12hour ? (hour === "" ? "" : hour % 12) : hour
        this.minute = minute
        this.second = second
        this.ampm = this.use12hour ? (hour > 12 ? "PM" : "AM") : ""
      },
    },
    selectedTimeStr() {
      this.$emit("input", this.selectedTime)
    },
  },
  methods: {
    isDisabledItem(list, number) {
      const item = list.find(item => item.value === number)
      return item ? item.disabled : true
    },
    getMinValidNumber(list) {
      const min = list.find(item => !item.disabled)
      return min ? min.value : 0
    },
  },
}
</script>
