<template>
  <div class="vdatetime-popup">
    <div class="vdatetime-popup__header">
      <div v-if="title" class="vdatetime-popup__title">{{ title }}</div>
      <div class="vdatetime-popup__date">
        {{
          newDatetime.toLocaleString({
            hour: "2-digit",
            minute: "2-digit",
            hour12: false
          })
        }}
      </div>
    </div>
    <div class="vdatetime-popup__body">
      <datetime-time-picker
        :hour="hour"
        :minute="minute"
        :use12-hour="use12Hour"
        :hour-step="hourStep"
        :minute-step="minuteStep"
        :min-time="minTime"
        :max-time="maxTime"
        @change="onChangeTime"
      ></datetime-time-picker>
    </div>
    <div class="vdatetime-popup__actions">
      <div
        class="vdatetime-popup__actions__button vdatetime-popup__actions__button--cancel"
      >
        <v-btn text @click="cancel">{{ phrases.cancel }}</v-btn>
      </div>
      <div
        class="vdatetime-popup__actions__button vdatetime-popup__actions__button--confirm"
      >
        <v-btn text @click="confirm">{{ phrases.ok }}</v-btn>
      </div>
    </div>
  </div>
</template>

<script>
import { DateTime } from "luxon"
import {
  createFlowManager,
  createFlowManagerFromType
} from "vue-datetime/src/util"
import DatetimeTimePicker from "vue-datetime/src/DatetimeTimePicker"

const KEY_TAB = 9
const KEY_ENTER = 13
const KEY_ESC = 27

export default {
  name: "DatetimePopup",

  components: {
    DatetimeTimePicker
  },

  props: {
    value: {
      type: DateTime
    },
    datetime: {
      type: DateTime,
      required: true
    },
    phrases: {
      type: Object,
      default() {
        return {
          cancel: "Cancel",
          ok: "Ok"
        }
      }
    },
    type: {
      type: String,
      default: "date"
    },
    use12Hour: {
      type: Boolean,
      default: false
    },
    hourStep: {
      type: Number,
      default: 1
    },
    minuteStep: {
      type: Number,
      default: 1
    },
    minDatetime: {
      type: DateTime,
      default: null
    },
    maxDatetime: {
      type: DateTime,
      default: null
    },
    auto: {
      type: Boolean,
      default: false
    },
    weekStart: {
      type: Number,
      default: 1
    },
    flow: {
      type: Array
    },
    title: {
      type: String
    }
  },

  data() {
    const flowManager = this.flow
      ? createFlowManager(this.flow)
      : createFlowManagerFromType(this.type)

    return {
      newDatetime: this.datetime,
      flowManager,
      step: flowManager.first(),
      timePartsTouched: []
    }
  },

  computed: {
    year() {
      return this.newDatetime.year
    },
    month() {
      return this.newDatetime.month
    },
    day() {
      return this.newDatetime.day
    },
    hour() {
      return this.newDatetime.hour
    },
    minute() {
      return this.newDatetime.minute
    },
    minTime() {
      return this.minDatetime &&
        this.minDatetime.year === this.year &&
        this.minDatetime.month === this.month &&
        this.minDatetime.day === this.day
        ? this.minDatetime.toFormat("HH:mm")
        : null
    },
    maxTime() {
      return this.maxDatetime &&
        this.maxDatetime.year === this.year &&
        this.maxDatetime.month === this.month &&
        this.maxDatetime.day === this.day
        ? this.maxDatetime.toFormat("HH:mm")
        : null
    }
  },

  mounted() {
    document.addEventListener("keydown", this.onKeyDown)
  },

  beforeDestroy() {
    document.removeEventListener("keydown", this.onKeyDown)
  },

  methods: {
    nextStep() {
      this.step = this.flowManager.next(this.step)
      this.timePartsTouched = []

      if (this.step === "end") {
        this.$emit("confirm", this.newDatetime)
      }
    },
    confirm() {
      this.$emit("confirm", this.newDatetime)
    },
    cancel() {
      this.$emit("cancel")
    },
    onChangeTime({ hour, minute, suffixTouched }) {
      if (suffixTouched) {
        this.timePartsTouched.suffix = true
      }

      if (Number.isInteger(hour)) {
        this.newDatetime = this.newDatetime.set({ hour })
        this.timePartsTouched.hour = true
      }

      if (Number.isInteger(minute)) {
        this.newDatetime = this.newDatetime.set({ minute })
        this.timePartsTouched.minute = true
      }

      const goNext =
        this.auto &&
        this.timePartsTouched.hour &&
        this.timePartsTouched.minute &&
        (this.timePartsTouched.suffix || !this.use12Hour)

      if (goNext) {
        this.nextStep()
      }

      this.$emit("input", this.newDatetime)
    },
    onKeyDown(event) {
      switch (event.keyCode) {
        case KEY_ESC:
        case KEY_TAB:
          this.cancel()
          break

        case KEY_ENTER:
          this.nextStep()
          break
      }
    }
  }
}
</script>

<style>
.vdatetime-popup {
  width: 100%;
  border-radius: 4px;
  box-sizing: border-box;
  z-index: 1000;
  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.3);
  color: #444;
  line-height: 1.18;
  background: #fff;
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);

  & * {
    box-sizing: border-box;
  }
}

.vdatetime-popup__header {
  padding: 18px 30px;
  background: #3f51b5;
  color: #fff;
  font-size: 32px;
  border-top-left-radius: 4px;
  border-top-right-radius: 4px;
  border: 1px solid #fff;
}

.vdatetime-popup__title {
  margin-bottom: 8px;
  font-size: 21px;
  font-weight: 300;
}

.vdatetime-popup__date {
  line-height: 1;
  cursor: pointer;
  font-size: 70px;
}

.vdatetime-popup__actions {
  padding: 0 20px 10px 30px;
  text-align: right;
  margin-top: 10px;
}

.vdatetime-popup__actions__button {
  display: inline-block;
  border: none;
  padding: 0;
  background: transparent;
  font-size: 16px;
  color: #3f51b5;
  cursor: pointer;
  transition: color 0.3s;

  &:hover {
    color: #444;
  }
}
</style>
