<template>
  <div v-if="formState.ready" v-resize="onResize" class="my-n8">
    <gz-error :error-box-message="formState.errorBoxMessage"></gz-error>
    <v-sheet height="64">
      <v-toolbar flat class="ml-n3">
        <v-btn text :small="isXS" :large="issmAndUp" @click="setToday">
          {{ $ay.t("DateRangeToday") }}
        </v-btn>
        <v-btn fab text :small="isXS" @click="prev">
          <v-icon :small="isXS">$prev</v-icon>
        </v-btn>
        <v-btn fab text :small="isXS" @click="next">
          <v-icon :small="isXS">$next</v-icon>
        </v-btn>
        <v-toolbar-title v-if="$refs.calendar">
          <v-btn
            :small="isXS"
            :large="issmAndUp"
            text
            @click="viewType = 'month'"
          >
            {{ $refs.calendar.title }}</v-btn
          >
        </v-toolbar-title>
        <v-spacer v-if="issmAndUp"></v-spacer>
        <v-btn
          class="mr-3"
          fab
          text
          :small="isXS"
          :large="issmAndUp"
          @click="settingsDialog = true"
        >
          <v-icon :small="isXS">$ayiCog</v-icon>
        </v-btn>

        <v-menu bottom right>
          <template v-slot:activator="{ on, attrs }">
            <v-btn
              :small="isXS"
              :large="issmAndUp"
              text
              v-bind="attrs"
              v-on="on"
            >
              <span>{{ typeToLabel() }}</span>
              <v-icon right>$sort</v-icon>
            </v-btn>
          </template>
          <v-list>
            <v-list-item @click="viewType = 'day'">
              <v-list-item-title>{{ $ay.t("ScheduleDay") }}</v-list-item-title>
            </v-list-item>
            <v-list-item @click="viewType = 'week'">
              <v-list-item-title>{{ $ay.t("ScheduleWeek") }}</v-list-item-title>
            </v-list-item>
            <v-list-item @click="viewType = 'month'">
              <v-list-item-title>{{
                $ay.t("ScheduleMonth")
              }}</v-list-item-title>
            </v-list-item>
            <v-list-item @click="viewType = '4day'">
              <v-list-item-title>{{ $ay.t("Schedule4Day") }}</v-list-item-title>
            </v-list-item>
          </v-list>
        </v-menu>
      </v-toolbar>
    </v-sheet>

    <v-sheet :height="calendarHeight">
      <v-calendar
        ref="calendar"
        v-model="focus"
        color="primary"
        :events="events"
        :event-color="getEventColor"
        :type="viewType"
        :locale="languageName"
        :event-more-text="$ay.t('More')"
        :first-time="formUserOptions.firstTime"
        :weekdays="weekdays"
        event-overlap-mode="column"
        @click:more="viewDay"
        @click:date="viewDay"
        @change="fetchEvents"
        @mousedown:event="startDrag"
        @mousedown:time="startTime"
        @mousemove:time="mouseMoveDayView"
        @mousemove:day="mouseMoveMonthView"
        @mouseup:day="endDragExtend"
        @mouseup:time="endDragExtend"
        @mouseleave.native="cancelDrag"
      >
        <template v-slot:event="{ event, timed, eventSummary }">
          <div class="v-event-draggable">
            <v-icon small :color="event.textColor" class="mr-1">{{
              iconForEvent(event.type)
            }}</v-icon>
            <!-- eslint-disable vue/no-v-html -->
            <span
              :class="event.textColor + '--text'"
              v-html="eventSummary()"
            /><v-icon
              v-if="!event.editable"
              x-small
              :color="event.textColor"
              class="ml-n3"
            >
              $ayiLock</v-icon
            >
          </div>
          <div
            v-if="timed && event.editable"
            class="v-event-drag-bottom"
            @mousedown.stop="extendBottom(event)"
          ></div>
        </template>
      </v-calendar>
      <!-- NEW ITEM DIALOG -->
      <template>
        <v-row dense justify="center">
          <v-dialog v-model="newItemDialog" max-width="360px" persistent>
            <v-card>
              <v-card-title>{{ $ay.t("New") }}</v-card-title>
              <v-card-text>
                <v-col cols="12">
                  <v-btn
                    x-large
                    block
                    @click="newItem($ay.ayt().WorkOrderItemScheduledUser)"
                    ><v-icon large left>$ayiTools</v-icon
                    >{{ $ay.t("WorkOrder") }}</v-btn
                  >
                </v-col>
                <!-- <v-col cols="12">
                  <v-btn x-large block @click="newItem($ay.ayt().Reminder)"
                    ><v-icon large left>$ayiStickyNote</v-icon
                    >{{ $ay.t("Reminder") }}</v-btn
                  >
                </v-col> -->
              </v-card-text>
              <v-card-actions>
                <v-btn text color="primary" @click="cancelAddNew">{{
                  $ay.t("Cancel")
                }}</v-btn>
              </v-card-actions>
            </v-card>
          </v-dialog>
        </v-row>
      </template>
      <!-- MORE INFO DIALOG -->
      <template>
        <v-row dense justify="center">
          <v-dialog v-model="moreInfoDialog" max-width="600px">
            <v-card>
              <v-toolbar>
                <v-btn icon @click="openScheduledItem()">
                  <v-icon color="primary">{{ iconForSelectedEvent() }}</v-icon>
                </v-btn>
                <v-toolbar-title>{{ selectedEvent.name }}</v-toolbar-title>
              </v-toolbar>
              <v-card-text>
                <!--woitemscheduleduser -->
                <template>
                  <div>
                    <span class="text-h6">{{ $ay.t("WorkOrder") }}:</span>
                    <span class="text-body-1 ml-2"
                      >{{ evInfo.serial }}&nbsp; {{ evInfo.customerViz }}</span
                    >
                  </div>
                  <div>
                    {{ evInfo.wosummary }}
                  </div>
                  <div>
                    <span class="text-h6">{{ $ay.t("Tags") }}:</span>
                    <span class="text-body-1 ml-2">{{
                      $ay.util().formatTags(evInfo.wotags)
                    }}</span>
                  </div>
                  <div>
                    <span class="text-h6"
                      >{{ $ay.t("WorkOrderItemScheduledUserUserID") }}:</span
                    >
                    <span class="text-body-1 ml-2">{{ evInfo.scheduser }}</span>
                  </div>
                  <div>
                    <span class="text-h6"
                      >{{ $ay.t("DashboardScheduled") }}:</span
                    >
                    <span class="text-body-1 ml-2"
                      >{{ $ay.dt(evInfo.startDate) }}&nbsp;&mdash;&nbsp;{{
                        $ay.dt(evInfo.stopDate)
                      }}</span
                    >
                  </div>
                  <div>
                    <span class="text-h6"
                      >{{
                        $ay.t("WorkOrderItemScheduledUserEstimatedQuantity")
                      }}:</span
                    >
                    <span class="text-body-1 ml-2">{{ evInfo.qty }}</span>
                  </div>
                  <div>
                    <span class="text-h6"
                      >{{
                        $ay.t("WorkOrderItemScheduledUserServiceRateID")
                      }}:</span
                    >
                    <span class="text-body-1 ml-2">{{ evInfo.rate }}</span>
                  </div>

                  <div v-if="evInfo.haswostatus">
                    <span class="text-h6">{{ $ay.t("WorkOrderStatus") }}:</span>
                    <span class="text-body-1 ml-2">{{ evInfo.wostatus }}</span>
                    <v-icon :color="evInfo.wostatuscolor" class="ml-4"
                      >$ayiFlag</v-icon
                    >
                    <v-icon
                      v-if="evInfo.wostatuslocked"
                      color="primary"
                      class="ml-4"
                      >$ayiLock</v-icon
                    >
                    <v-icon
                      v-if="evInfo.wostatuscompleted"
                      color="primary"
                      class="ml-4"
                      >$ayiCheckCircle</v-icon
                    >
                  </div>

                  <div>
                    <span class="text-h6"
                      >{{ $ay.t("WorkOrderItemSummary") }}:</span
                    >
                    <span class="text-body-1 ml-2">
                      <v-icon class="mr-3" :color="evInfo.woitemstatuscolor"
                        >$ayiCircle</v-icon
                      >{{ evInfo.woitemstatus }}</span
                    >
                  </div>

                  <div>
                    <span class="text-h6"
                      >{{ $ay.t("WorkOrderItemPriorityID") }}:</span
                    >
                    <span class="text-body-1 ml-2">
                      <v-icon class="mr-3" :color="evInfo.woitemprioritycolor"
                        >$ayiFireAlt</v-icon
                      >{{ evInfo.woitempriority }}</span
                    >
                  </div>
                  <div>
                    <span class="text-h6"
                      >{{ $ay.t("WorkOrderItemTags") }}:</span
                    >
                    <span class="text-body-1 ml-2">{{
                      $ay.util().formatTags(evInfo.woitemtags)
                    }}</span>
                  </div>
                </template>
              </v-card-text>
              <v-card-actions>
                <v-btn color="primary" text @click="openScheduledItem()">{{
                  $ay.t("Open")
                }}</v-btn>

                <v-spacer v-if="!$vuetify.breakpoint.xs"></v-spacer>

                <v-btn color="primary" text @click="moreInfoDialog = false">
                  {{ $ay.t("Close") }}
                </v-btn>
              </v-card-actions>
            </v-card>
          </v-dialog>
        </v-row>
      </template>
    </v-sheet>
    <template>
      <!-- ############## SETTINGS DIALOG #################-->
      <v-row dense justify="center">
        <v-dialog v-model="settingsDialog" max-width="600px">
          <v-card>
            <v-card-title>{{ $ay.t("ScheduleOptions") }} </v-card-title>
            <v-card-text>
              <v-row no-gutters>
                <v-col cols="12" class="mt-2">
                  <gz-time-picker
                    v-model="tempFirstTime"
                    :label="$ay.t('ScheduleFirstHour')"
                  ></gz-time-picker>
                </v-col>

                <v-col cols="12">
                  <GZDaysOfWeek
                    ref="daysofweek"
                    v-model="formUserOptions.excludeDaysOfWeek"
                    :label="$ay.t('ExcludeDaysOfWeek')"
                  ></GZDaysOfWeek>
                </v-col>

                <span class="text-h6 mt-3">{{
                  $ay.t("ScheduleShowTypes")
                }}</span>
                <v-col cols="12">
                  <v-checkbox
                    v-model="formUserOptions.reminders"
                    dense
                    :label="$ay.t('ReminderList')"
                  ></v-checkbox>
                </v-col>
                <v-col cols="12">
                  <v-checkbox
                    v-model="formUserOptions.reviews"
                    dense
                    :label="$ay.t('ReviewList')"
                  ></v-checkbox>
                </v-col>

                <v-col cols="12">
                  <v-checkbox
                    v-model="formUserOptions.wisu"
                    dense
                    :label="$ay.t('WorkOrderList')"
                  ></v-checkbox>

                  <v-radio-group
                    v-model="formUserOptions.wisuColorSource"
                    dense
                    :mandatory="true"
                    :label="$ay.t('ScheduleWOColorFrom')"
                    class="ml-3 mt-n2"
                  >
                    <v-radio :label="$ay.t('NoColor')" value="0"></v-radio>
                    <v-radio
                      :label="$ay.t('WorkOrderStatus')"
                      value="2"
                    ></v-radio>
                    <v-radio
                      :label="$ay.t('WorkOrderItemWorkOrderStatusID')"
                      value="3"
                    ></v-radio>
                    <v-radio
                      :label="$ay.t('WorkOrderItemPriorityID')"
                      value="4"
                    ></v-radio>
                  </v-radio-group>
                </v-col>
              </v-row>
            </v-card-text>
            <v-card-actions>
              <v-btn text color="primary" @click="settingsDialog = false">{{
                $ay.t("Cancel")
              }}</v-btn>
              <v-spacer v-if="issmAndUp"></v-spacer>
              <v-btn
                color="primary"
                text
                class="ml-4"
                @click="saveUserOptions()"
                >{{ $ay.t("Save") }}</v-btn
              >
            </v-card-actions>
          </v-card>
        </v-dialog>
      </v-row>
    </template>
  </div>
</template>
<script>
const FORM_KEY = "svc-schedule-user";
import GZDaysOfWeek from "../components/days-of-week-control.vue";
export default {
  components: {
    GZDaysOfWeek
  },
  data() {
    return {
      focus: "",
      viewType: "month",
      selectedEvent: {},
      selectedElement: null,
      events: [],
      evInfo: {},
      dragEvent: null,
      extendEvent: null,
      createStart: null,
      extendOriginal: null,
      dragged: false,
      dragTimeout: null,
      formState: {
        ready: false,
        dirty: false,
        valid: true,
        readOnly: false,
        loading: true,
        errorBoxMessage: null,
        appError: null,
        serverError: {}
      },
      calendarHeight: 600,
      settingsDialog: false,
      newItemDialog: false,
      moreInfoDialog: false,
      timeZoneName: window.$gz.locale.getResolvedTimeZoneName(),
      languageName: window.$gz.locale.getResolvedLanguage(),
      hour12: window.$gz.locale.getHour12(),
      formUserOptions: {},
      tempFirstTime: null,
      lastMouseDownMS: null,
      lastStart: null,
      lastEnd: null,
      userId: null,
      userName: null
    };
  },
  computed: {
    weekdays() {
      return window.$gz.util.DaysOfWeekToWeekdays(
        this.formUserOptions.excludeDaysOfWeek
      );
    },
    isXS() {
      //console.log(this.$vuetify.breakpoint);
      return this.$vuetify.breakpoint.xs;
    },
    issmAndUp() {
      return this.$vuetify.breakpoint.smAndUp;
    }
  },
  async created() {
    const vm = this;
    try {
      this.userId = vm.$route.params.recordid;
      this.userName = vm.$route.params.name;
      await initForm(vm);
      window.$gz.eventBus.$on("menu-click", clickHandler);
      //----------------------------
      generateMenu(vm);
    } catch (error) {
      window.$gz.errorHandler.handleFormError(error, vm);
    } finally {
      vm.formState.ready = true;
    }
  },
  beforeDestroy() {
    saveFormSettings(this);
    window.$gz.eventBus.$off("menu-click", clickHandler);
  },
  methods: {
    async refresh() {
      await this.fetchEvents({ start: null, end: null });
    },
    openObject: function(type, id) {
      window.$gz.eventBus.$emit("openobject", {
        type: type,
        id: id
      });
    },
    newItem(atype) {
      const newEvent = this.events[this.events.length - 1];
      const addStart = window.$gz.locale.localScheduleFormatToUTC8601String(
        newEvent.start,
        this.timeZoneName
      );
      const addEnd = window.$gz.locale.localScheduleFormatToUTC8601String(
        newEvent.end,
        this.timeZoneName
      );
      switch (atype) {
        case this.$ay.ayt().WorkOrderItemScheduledUser:
          this.$router.push({
            name: "workorder-edit",
            params: {
              recordid: 0,
              add: {
                type: atype,
                start: addStart,
                end: addEnd,
                userId: this.userId == 0 ? null : this.userId,
                name: this.userId == 0 ? null : this.userName
              }
            }
          });
          break;
      }
      //remove faux item, server will provide it back once it's created anyway
      this.events.splice(this.events.length - 1);
      this.newItemDialog = false;
    },
    cancelAddNew() {
      this.events.splice(this.events.length - 1);
      this.newItemDialog = false;
    },

    extendBottom(event) {
      //console.log("extend bottom fired");
      if (event.editable) {
        //capture time to see if it's a click or a drag/extend
        this.lastMouseDownMS = new Date().getTime();
        this.extendEvent = event;
        this.createStart = event.start;
        this.extendOriginal = event.end;
      }
    },
    async endDragExtend() {
      //On drag then dragged is set to true and dragEvent and dragTime are set
      //on extend then dragged is set to true extendEvent (actual event), extendOriginal and createStart are set, dragEvent is null
      //on create then dragged is set to false and createStart is only value set, dragEvent is null and extendEvent is null

      //Handle the event, could be one of three things: changing an event start time, changing an event length or creating a new event
      if (this.extendEvent && this.extendEvent.type == 0) {
        //NEW, prompt for deets and create or if cancelled then just remove this faux event from events list (it will be the last one in the array)
        this.newItemDialog = true;
      } else {
        //MORE INFO
        if (this.lastMouseDownMS != null && this.itWasAClickNotADrag()) {
          await this.showMoreInfo(this.dragEvent);
          this.dragEvent = null; //this needs to be set or it will keep dragging off an editable event even as the moreinfo dialog show
          return;
        }

        //MODIFY existing event, drag or extend
        if (this.dragEvent || this.extendEvent) {
          const param = {
            type: null,
            id: null,
            start: null,
            end: null,
            userId: this.userId //always whatever user id we came in for from svc-schedule
          };

          if (this.dragEvent) {
            param.type = this.dragEvent.type;
            param.id = this.dragEvent.id;
            param.start = window.$gz.locale.localScheduleFormatToUTC8601String(
              this.dragEvent.start,
              this.timeZoneName
            );
            param.end = window.$gz.locale.localScheduleFormatToUTC8601String(
              this.dragEvent.end,
              this.timeZoneName
            );
          } else {
            param.type = this.extendEvent.type;
            param.id = this.extendEvent.id;
            param.start = window.$gz.locale.localScheduleFormatToUTC8601String(
              this.extendEvent.start,
              this.timeZoneName
            );
            param.end = window.$gz.locale.localScheduleFormatToUTC8601String(
              this.extendEvent.end,
              this.timeZoneName
            );
          }
          try {
            window.$gz.form.deleteAllErrorBoxErrors(this);
            const res = await window.$gz.api.post("schedule/adjust", param);
            if (res.error) {
              this.formState.serverError = res.error;
              window.$gz.form.setErrorBoxErrors(this);
            }
          } catch (error) {
            window.$gz.errorHandler.handleFormError(error, this);
          }
        }
      }
      this.dragTime = null;
      this.dragEvent = null;
      this.extendEvent = null;
      this.createStart = null;
      this.extendOriginal = null;
    },
    cancelDrag() {
      if (this.extendEvent) {
        if (this.extendOriginal) {
          this.extendEvent.end = this.extendOriginal;
        } else {
          const i = this.events.indexOf(this.extendEvent);
          if (i !== -1) {
            this.events.splice(i, 1);
          }
        }
      }
      this.extendEvent = null;
      this.createStart = null;
      this.dragTime = null;
      this.dragEvent = null;
      this.lastMouseDownMS = null;
    },
    startDrag({ event }) {
      //# mouse down on an event triggers this call
      if (event) {
        this.lastMouseDownMS = new Date().getTime(); //snapshot time to disambiguate drag vs click
        if (event.editable) {
          this.dragged = false;
          this.dragEvent = event;
          this.dragTime = null;
          this.extendOriginal = null;
        } else {
          this.dragged = false;
          this.dragEvent = event;
          this.dragTime = null;
        }
      }
    },
    itWasAClickNotADrag() {
      if (this.lastMouseDownMS == null) {
        if (this.$ay.dev) {
          throw new Error("lastMouseDownMS is null!");
        } else {
          window.$gz.store.commit(
            "logItem",
            "home-schedule:lastMouseDownMS is unexpectedly null"
          );
          return true; //least dangerous option in production
        }
      }
      const elapsed = new Date().getTime() - this.lastMouseDownMS;
      this.lastMouseDownMS = null;
      return elapsed < 200;
    },
    mouseMoveDayView(tms) {
      //no event being dragged or exgtended?
      if (!this.dragEvent && !this.extendEvent) {
        return;
      }
      const mouse = this.toTime(tms);
      if (this.dragEvent && this.dragTime !== null) {
        //# DRAGGING PATH
        const start = this.dragEvent.start;
        const end = this.dragEvent.end;
        const duration = end - start;
        const newStartTime = mouse - this.dragTime;
        const newStart = this.roundTime(newStartTime);
        const newEnd = newStart + duration;
        this.dragEvent.start = newStart;
        this.dragEvent.end = newEnd;
      } else if (this.extendEvent && this.createStart !== null) {
        //# EXTENDING PATH
        const mouseRounded = this.roundTime(mouse, false);
        const min = Math.min(mouseRounded, this.createStart);
        const max = Math.max(mouseRounded, this.createStart);
        this.extendEvent.start = min;
        this.extendEvent.end = max;
      }
    },
    mouseMoveMonthView(dd) {
      if (!this.dragEvent) {
        return;
      }
      //# DRAGGING PATH MONTH VIEW
      //need to get the actual start time as it isn't in the mouse date
      const dragEventStartDate = new Date(this.dragEvent.start);
      const mouseDate = new Date(
        dd.year,
        dd.month - 1,
        dd.day,
        dragEventStartDate.getHours(),
        dragEventStartDate.getMinutes()
      ).getTime();
      const moveDelta = mouseDate - this.dragEvent.start;
      this.dragEvent.start = mouseDate;
      this.dragEvent.end = this.dragEvent.end + moveDelta;
    },
    startTime(tms) {
      //This is called on the start of dragging an existing schedule item or drag extending a NEW schedule item
      const mouse = this.toTime(tms);
      if (this.dragEvent && this.dragTime === null) {
        //# DAY VIEW *DRAG* EXISTING START EVENT (not extend)
        //(also called on simple click to view schedule more info)
        if (this.dragEvent.editable) {
          const start = this.dragEvent.start;
          this.dragTime = mouse - start;
        }
      } else {
        //# DAY VIEW CREATE START EVENT
        this.createStart = this.roundTime(mouse);
        this.extendEvent = {
          name: "-",
          color: this.$store.state.darkMode ? "white" : "black",
          textColor: this.$store.state.darkMode ? "black" : "white",
          start: this.createStart,
          end: this.createStart,
          timed: true,
          type: 0,
          id: 0,
          editable: true
        };
        this.events.push(this.extendEvent);
      }
    },
    roundTime(time, down = true) {
      const roundTo = 15; // minutes
      const roundDownTime = roundTo * 60 * 1000;
      return down
        ? time - (time % roundDownTime)
        : time + (roundDownTime - (time % roundDownTime));
    },
    toTime(tms) {
      return new Date(
        tms.year,
        tms.month - 1,
        tms.day,
        tms.hour,
        tms.minute
      ).getTime();
    },
    typeToLabel() {
      switch (this.viewType) {
        case "month":
          return this.$ay.t("ScheduleMonth");
        case "week":
          return this.$ay.t("ScheduleWeek");
        case "day":
          return this.$ay.t("ScheduleDay");
        case "4day":
          return this.$ay.t("Schedule4Day");
      }
    },
    onResize() {
      this.calendarHeight = window.innerHeight * 0.84;
    },
    viewDay({ date }) {
      //console.log("ViewDay clicked");
      this.focus = date;
      this.viewType = "day";
    },
    getEventColor(event) {
      return event.color;
    },
    setToday() {
      this.focus = "";
    },
    prev() {
      this.$refs.calendar.prev();
    },
    next() {
      this.$refs.calendar.next();
    },
    iconForSelectedEvent() {
      return window.$gz.util.iconForType(this.selectedEvent.type);
    },
    iconForEvent(type) {
      return window.$gz.util.iconForType(type);
    },
    openScheduledItem() {
      window.$gz.eventBus.$emit("openobject", {
        type: this.selectedEvent.type,
        id: this.selectedEvent.id
      });
    },
    async showMoreInfo(event) {
      this.selectedEvent = event;
      let route = null;
      this.evInfo = {};
      switch (event.type) {
        case window.$gz.type.WorkOrderItemScheduledUser:
          route = `workorder/items/scheduled-users/sched-info/${event.id}`;
          break;
        // case window.$gz.type.Reminder:
        //   route = `reminder/sched-info/${event.id}`;
        //   break;
        // case window.$gz.type.Review:
        //   route = `review/sched-info/${event.id}`;
        //   break;
      }
      if (route) {
        const res = await window.$gz.api.get(route);
        if (!res.error) {
          this.evInfo = res.data;
          this.moreInfoDialog = true;
        } else {
          this.formState.serverError = res.error;
          window.$gz.form.setErrorBoxErrors(this);
        }
      }
    },
    async fetchEvents({ start, end }) {
      if (start) {
        this.lastStart = start;
        this.lastEnd = end;
      } else {
        start = this.lastStart;
        end = this.lastEnd;
      }
      try {
        window.$gz.form.deleteAllErrorBoxErrors(this);
        const res = await window.$gz.api.post("schedule/user", {
          view: window.$gz.util.calendarViewToAyaNovaEnum(this.viewType),
          dark: this.$store.state.darkMode,
          start: window.$gz.locale.localTimeDateStringToUTC8601String(
            `${start.date}T00:00:00`,
            this.timeZoneName
          ),
          end: window.$gz.locale.localTimeDateStringToUTC8601String(
            `${end.date}T23:59:59`,
            this.timeZoneName
          ),
          wisuColorSource: this.formUserOptions.wisuColorSource,
          wisu: this.formUserOptions.wisu, //workorder item scheduled user records
          reviews: this.formUserOptions.reviews,
          reminders: this.formUserOptions.reminders,
          userId: this.userId
        });
        if (res.error) {
          this.formState.serverError = res.error;
          window.$gz.form.setErrorBoxErrors(this);
        } else {
          this.events.splice(0);
          const timeZoneName = this.timeZoneName;
          let i = res.data.length;
          while (i--) {
            const x = res.data[i];
            this.events.push({
              start: new Date(
                new Date(x.start)
                  .toLocaleString("sv-SE", {
                    timeZone: timeZoneName
                  })
                  .replace(" ", "T")
              ).getTime(),
              end: new Date(
                new Date(x.end)
                  .toLocaleString("sv-SE", {
                    timeZone: timeZoneName
                  })
                  .replace(" ", "T")
              ).getTime(),
              timed: true,
              name: x.name,
              color: x.color,
              textColor: x.textColor,
              type: x.type,
              id: x.id,
              editable: x.editable,
              userId: x.userId
            });
          }
        }
      } catch (error) {
        window.$gz.errorHandler.handleFormError(error, this);
      }
    },
    async saveUserOptions() {
      this.settingsDialog = false;
      await saveFormUserOptions(this);
      await this.refresh();
    }
    //eom
  }
};

/////////////////////////////
//
//
async function clickHandler(menuItem) {
  if (!menuItem) {
    return;
  }
  const m = window.$gz.menu.parseMenuItem(menuItem);
  if (m.owner == FORM_KEY && !m.disabled) {
    switch (m.key) {
      // case "report":
      //   const res = await m.vm.$refs.reportSelector.open(
      //     {
      //       AType: window.$gz.type.Project,
      //       selectedRowIds: [m.vm.obj.id]
      //     },
      //     m.id
      //   );
      //   if (res == null) {
      //     return;
      //   }
      //
      // window.$gz.form.setLastReportMenuItem(FORM_KEY, res, m.vm);
      //   break;
      case "WorkOrderItemScheduledUserList":
        m.vm.$router.push({
          name: "svc-workorder-item-scheduled-users",
          params: {
            aType: window.$gz.type.User,
            objectId: m.vm.userId,
            name: m.vm.userName
          }
        });
        break;
      case "WorkOrderItemLaborList":
        m.vm.$router.push({
          name: "svc-workorder-item-labors",
          params: {
            aType: window.$gz.type.User,
            objectId: m.vm.userId,
            name: m.vm.userName
          }
        });
        break;

      case "ReminderList":
        m.vm.$router.push({
          name: "home-reminders"
        });
        break;

      case "ReviewList":
        m.vm.$router.push({
          name: "home-reviews"
        });
        break;
      case "newcustomer":
        m.vm.$router.push({
          name: "customer-edit",
          params: { recordid: 0 }
        });
        break;
      default:
        window.$gz.eventBus.$emit(
          "notify-warning",
          FORM_KEY + "::context click: [" + m.key + "]"
        );
    }
  }
}

//////////////////////
//
//
function generateMenu(vm) {
  const menuOptions = {
    isMain: true,
    readOnly: vm.formState.readOnly,
    icon: "$ayiCalendarDay",
    title: "Schedule",
    helpUrl: "svc-schedule",
    formData: {
      recordName: vm.userName
    },
    menuItems: []
  };

  //  //
  // menuOptions.menuItems.push({
  //   title: "Report",
  //   icon: "$ayiFileAlt",
  //   key: FORM_KEY + ":report",
  //   vm: vm
  // });

  //
  // const lastReport = window.$gz.form.getLastReport(FORM_KEY);
  // if (lastReport != null) {
  //   menuOptions.menuItems.push({
  //     title: lastReport.name,
  //     notrans: true,
  //     icon: "$ayiFileAlt",
  //     key: FORM_KEY + ":report:" + lastReport.id,
  //     vm: vm
  //   });
  // }

  //   menuOptions.menuItems.push({
  //     title: "ReminderList",
  //     icon: "$ayiStickyNote",
  //     key: FORM_KEY + ":ReminderList",
  //     vm: vm
  //   });

  //   menuOptions.menuItems.push({
  //     title: "ReviewList",
  //     icon: "$ayiCalendarCheck",
  //     key: FORM_KEY + ":ReviewList",
  //     vm: vm
  //   });

  menuOptions.menuItems.push({ divider: true, inset: false });
  if (window.$gz.role.canChange(window.$gz.type.Customer)) {
    menuOptions.menuItems.push({
      title: "NewCustomer",
      icon: "$ayiAddressCard",
      key: FORM_KEY + ":newcustomer",
      vm: vm
    });
  }
  menuOptions.menuItems.push({
    title: "WorkOrderItemScheduledUserList",
    icon: "$ayiUserClock",
    key: FORM_KEY + ":WorkOrderItemScheduledUserList",
    vm: vm
  });

  if (vm.userId != 0) {
    menuOptions.menuItems.push({
      title: "WorkOrderItemLaborList",
      icon: "$ayiHammer",
      key: FORM_KEY + ":WorkOrderItemLaborList",
      vm: vm
    });
  }

  menuOptions.menuItems.push({ divider: true, inset: false });

  window.$gz.eventBus.$emit("menu-change", menuOptions);
}

/////////////////////////////////
//
//
async function initForm(vm) {
  await fetchTranslatedText();
  getFormSettings(vm);
  await getFormUserOptions(vm);
}

function getFormSettings(vm) {
  let formSettings = window.$gz.form.getFormSettings(FORM_KEY);
  if (!formSettings || !formSettings.temp || !formSettings.temp.viewType) {
    //defaults
    formSettings = { temp: { viewType: "month", focus: null } };
  }

  vm.viewType = formSettings.temp.viewType;
  vm.focus = formSettings.temp.focus;

  return formSettings;
}

function saveFormSettings(vm) {
  const formSettings = window.$gz.form.getFormSettings(FORM_KEY);
  formSettings.temp = { viewType: vm.viewType, focus: vm.focus };

  window.$gz.form.setFormSettings(FORM_KEY, formSettings);
}

////////////////////
//
async function getFormUserOptions(vm) {
  const res = await window.$gz.api.get(`form-user-options/${FORM_KEY}`);
  if (res.error) {
    vm.formState.serverError = res.error;
    window.$gz.form.setErrorBoxErrors(vm);
  } else {
    if (res.data == null) {
      //make a default
      vm.formUserOptions = {
        firstTime: "00:00",
        excludeDaysOfWeek: 0,
        wisuColorSource: "2",
        wisu: true,
        reviews: true,
        reminders: true
      };
    } else {
      vm.formUserOptions = JSON.parse(res.data.options);
    }
    //takes local time in "HH:MM" format and converts to ISO UTC format for picker consumption
    const d = new Date();
    const temp = new Date(
      d.getFullYear(),
      d.getMonth(),
      d.getDate(),
      vm.formUserOptions.firstTime.split(":")[0],
      vm.formUserOptions.firstTime.split(":")[1]
    );
    vm.tempFirstTime = window.$gz.locale.localTimeDateStringToUTC8601String(
      temp.toISOString(),
      vm.timeZoneName
    );
  }
}

////////////////////
//
async function saveFormUserOptions(vm) {
  //translate tempFirstTime to local time
  if (vm.tempFirstTime) {
    //convert picker's utc time to local hour:MM
    const localTime = window.$gz.DateTime.fromISO(vm.tempFirstTime).toLocal();
    vm.formUserOptions.firstTime = `${localTime.hour}:${localTime.minute}`;
  }
  const res = await window.$gz.api.post("form-user-options", {
    formKey: FORM_KEY,
    options: JSON.stringify(vm.formUserOptions)
  });
  if (res.error) {
    vm.formState.serverError = res.error;
    window.$gz.form.setErrorBoxErrors(vm);
  }
}

//////////////////////////////////////////////////////////
//
// Ensures UI translated text is available
//
async function fetchTranslatedText() {
  await window.$gz.translation.cacheTranslations([
    "DateRangeToday",
    "ExcludeDaysOfWeek",
    "ScheduleMonth",
    "ScheduleDay",
    "ScheduleWeek",
    "Schedule4Day",
    "ScheduleFirstHour",
    "ScheduleWOColorFrom",
    "ScheduleOptions",
    "ScheduleShowTypes",
    "NoColor",
    "WorkOrder",
    "Reminder",
    "WorkOrderList",
    "ReminderList",
    "ReviewList",
    "DashboardScheduled",
    "WorkOrderItemScheduledUserUserID",
    "WorkOrderItemPriorityID",
    "WorkOrderItemSummary",
    "WorkOrderItemWorkOrderStatusID",
    "WorkOrderStatus",
    "WorkOrderItemScheduledUserEstimatedQuantity",
    "WorkOrderItemScheduledUserServiceRateID",
    "WorkOrderItemTags",
    "ReminderName",
    "ReviewDate",
    "ReminderNotes",
    "ReviewName",
    "ReviewNotes",
    "ReviewCompletedDate",
    "ReviewCompletionNotes",
    "NewCustomer"
  ]);
}
</script>
<style scoped lang="scss">
.v-event-draggable {
  padding-left: 6px;
}

.v-event-timed {
  user-select: none;
  -webkit-user-select: none;
}

.v-event-drag-bottom {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 4px;
  height: 4px;
  cursor: ns-resize;

  &::after {
    display: none;
    position: absolute;
    left: 50%;
    height: 4px;
    border-top: 1px solid gray;
    border-bottom: 1px solid gray;
    width: 32px;
    margin-left: -8px;
    // opacity: 0.8;
    content: "";
  }

  &:hover::after {
    display: block;
  }
}
</style>
