<template>
  <div v-if="formState.ready" v-resize="onResize" class="my-n8">
    <!-- `{{ "focus:" + focus }}` {{ diagInfo() }}
    {{ evInfo }}
    {{ events }}-->
    <gz-error :error-box-message="formState.errorBoxMessage"></gz-error>

    <v-sheet height="64">
      <v-toolbar flat class="ml-n3">
        <v-btn outlined class="xxmr-4" color="grey darken-2" @click="setToday">
          {{ $ay.t("DateRangeToday") }}
        </v-btn>
        <v-btn fab text small color="grey darken-2" @click="prev">
          <v-icon small>$prev</v-icon>
        </v-btn>
        <v-btn fab text small color="grey darken-2" @click="next">
          <v-icon small>$next</v-icon>
        </v-btn>
        <v-toolbar-title v-if="$refs.calendar">
          <v-btn text @click="viewType = 'month'">
            {{ $refs.calendar.title }}</v-btn
          >
        </v-toolbar-title>
        <v-spacer v-if="!$vuetify.breakpoint.xs"></v-spacer>
        <v-btn
          class="mr-3"
          fab
          text
          small
          color="grey darken-2"
          @click="settingsDialog = true"
        >
          <v-icon small>$ayiCog</v-icon>
        </v-btn>

        <v-menu bottom right>
          <template v-slot:activator="{ on, attrs }">
            <v-btn outlined color="grey darken-2" 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"
        @click:event="showMoreInfo"
        @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"
      >
        <!--
         @touchstart:time="startTime"
        
      @touchmove:time="mouseMoveDa
        @touchend:event="touchEndEvent"
        @touchstart:event="touchStartEvent"yView"
       @touchmove:day="mouseMoveMonthView" 
       @touchend:day="endDragExtend" 
       @touchend:time="endDragExtend"
      -->
        <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>

            <span
              :class="event.textColor + '--text'"
              v-html="eventSummary()"
            /><v-icon
              v-if="!event.editable"
              x-small
              :color="event.textColor"
              class="ml-1"
            >
              $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 justify="center">
          <v-dialog max-width="360px" persistent v-model="newItemDialog">
            <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 @click="cancelAddNew" color="primary">{{
                  $ay.t("Cancel")
                }}</v-btn>
              </v-card-actions>
            </v-card>
          </v-dialog>
        </v-row>
      </template>
      <!-- MORE INFO DIALOG -->
      <v-menu
        v-model="moreInfoDialog"
        :close-on-content-click="false"
        :activator="selectedElement"
        offset-x
      >
        <v-card color="grey lighten-4" min-width="350px" flat>
          <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>
            <!--reminder -->
            <template v-if="selectedEvent.type == $ay.ayt().Reminder">
              <div>
                <span class="text-h6">{{ $ay.t("ReminderName") }}:</span>
                <span class="text-body-1 ml-2">{{ evInfo.name }}</span>
              </div>
              <div>
                <span class="text-h6">{{ $ay.t("ReviewDate") }}:</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("ReminderNotes") }}:</span>
                <span class="text-body-1 ml-2">
                  <v-icon class="mr-3" :color="evInfo.color"
                    >$ayiSquareFull</v-icon
                  >{{ evInfo.notes }}</span
                >
              </div>
            </template>
            <!--review -->
            <template v-if="selectedEvent.type == $ay.ayt().Review">
              <div class="mb-1" v-if="evInfo.aType">
                <v-icon
                  large
                  color="primary"
                  @click="openObject(evInfo.aType, evInfo.objectId)"
                  >{{ $ay.util().iconForType(evInfo.aType) }}</v-icon
                ><span
                  class="text-h6"
                  @click="openObject(evInfo.aType, evInfo.objectId)"
                >
                  {{ evInfo.reviewObjectViz }}</span
                >
              </div>
              <div>
                <span class="text-h6">{{ $ay.t("ReviewName") }}:</span>
                <span class="text-body-1 ml-2">{{ evInfo.name }}</span>
              </div>
              <div>
                <span class="text-h6">{{ $ay.t("ReviewDate") }}:</span>
                <span class="text-body-1 ml-2">{{
                  $ay.dt(evInfo.reviewDate)
                }}</span>
              </div>
              <div>
                <span class="text-h6">{{ $ay.t("ReviewNotes") }}:</span>
                <span class="text-body-1 ml-2"> {{ evInfo.notes }}</span>
              </div>

              <template v-if="evInfo.completedDate">
                <div>
                  <span class="text-h6"
                    >{{ $ay.t("ReviewCompletedDate") }}:</span
                  >
                  <span class="text-body-1 ml-2">{{
                    $ay.dt(evInfo.completedDate)
                  }}</span>
                </div>
                <div>
                  <span class="text-h6"
                    >{{ $ay.t("ReviewCompletionNotes") }}:</span
                  >
                  <span class="text-body-1 ml-2">
                    {{ evInfo.completionNotes }}</span
                  >
                </div>
              </template>
            </template>
            <!--woitemscheduleduser -->
            <template
              v-if="selectedEvent.type == $ay.ayt().WorkOrderItemScheduledUser"
            >
              <div>
                <span class="text-h6">{{ $ay.t("WorkOrder") }}:</span>
                <span class="text-body-1 ml-2"
                  >{{ evInfo.serial }}&nbsp; {{ evInfo.customerViz }}</span
                >
              </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("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
                  color="primary"
                  v-if="evInfo.wostatuslocked"
                  class="ml-4"
                  >$ayiLock</v-icon
                >
                <v-icon
                  color="primary"
                  v-if="evInfo.wostatuscompleted"
                  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-menu>
    </v-sheet>
    <template>
      <v-row justify="center">
        <v-dialog max-width="600px" v-model="settingsDialog">
          <v-card>
            <v-card-title> </v-card-title>
            <v-card-text>
              settings here
            </v-card-text>
            <v-card-actions>
              <v-btn text @click="settingsDialog = false" color="primary">{{
                $ay.t("Cancel")
              }}</v-btn>
              <v-spacer v-if="!$vuetify.breakpoint.xs"></v-spacer>
              <v-btn
                color="primary"
                text
                @click="acceptSettings()"
                class="ml-4"
                >{{ $ay.t("OK") }}</v-btn
              >
            </v-card-actions>
          </v-card>
        </v-dialog>
      </v-row>
    </template>
  </div>
</template>

<script>
/*

TODO NEXT:
  
Determine all settings required to persist (try to think of shared schedule too becuase want to use the same basic structure so one path to api)
  Store and retrieve as a single json object?
  then could re-use for potentially other things
  Like a route that stores per userid and formkey a single json object, null if none
    on change of settings persists when settings form closes
    does this supersede some user options?




Settings form
  Settings should be for the FORM, not the user so that a user can have different settings in personal schedule vs svc-schedule etc
  persist, imminentize    
  Save / load from server (or locally only? as formSettings.saved)??
    saved with device or saved with account is the heart of it
  wo display section:
    DISPLAY
      Color: wostatus/woitemstatus/woitempriority/none
      Weekdays: weekdays to display, copy from pm exclude days thingy
      More info: checkbox beside each item below that can be shown in wo

todo: Needs a refresh button somewhere to refresh for new appts.
  todo: ### find all trans keys and make sure they are fetched in initform ###

  TESTING:
    Test here locally and check for layout issues while doing it on all devices 
    drag/extend in all views working?      
    mobile device testing
    phones
    ipad
    shitty tablet
    NOTE: no need for drag drop extend on non mouse device, but do want it to be able to create at least near the touch point

  Move common functionality out of home-schedule to be re-used in svc-schedule and also potentially other scheds like customer view of workorders or visual calendar view of work for a single customer for techs etc
    the more I can move out of it the easier to do more scheds in other places

  DOCS:
    how to use the schedule

  Investigate: can AyaNova be a calendar source for Google calendar and others (like provide ical)
    so they can view, move around but create would be outside that but provided for when refresh.
    This way a user could just use their built in calendar app rather than fighting with our implementation
    Make a case with whatever is found if it looks like a v.next thing
    keywords google calendar feed url 
    https://stayrony.github.io/Create-iCal-ics-Files-in-net-Core/
    http://blog.bennymichielsen.be/2013/11/11/exposing-ical-data-in-webapi/
    https://blog.elmah.io/generate-calendar-in-ical-format-with-net-using-ical-net/
    https://stackoverflow.com/questions/49032408/i-am-trying-to-provide-google-calendar-with-url-of-calendar-served-by-iis-asp-n
    Looks like you just provide text back in ical format so would need a token system of some kind I guess since google calendar is not going to login
    Maybe a sync option via the ayanova app is what is needed, i.e. they have a menu option to download as ical or sync as ical in ayanova and the device recognizes the url protocol or other type and syncs
    this might be a workaround to security issues and users can just update as needed for offline working
    ical maybe has urls to open objects in it somehow as well so they can clickthrough google calendar to the source object??


  reporting - make it happen
    could just default to regular reporting list, doesn't absolutely need to be a calendar at least at first
    as long as it has all appointments consolidated in single list
  
Move on to the shared service schedule with categories being people and all that entails

*/

// const FORM_CUSTOM_TEMPLATE_KEY = "home-schedule";
const FORM_KEY = "home-schedule";
const CLICK_DETECT_TIMEOUT = 100;
export default {
  async created() {
    let vm = this;

    try {
      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);
  },
  data() {
    return {
      //formCustomTemplateKey: FORM_CUSTOM_TEMPLATE_KEY,
      focus: "",
      viewType: "month",
      selectedEvent: {},
      selectedElement: null,
      moreInfoDialog: false,
      events: [],
      evInfo: {},
      dragEvent: null,
      dragStart: 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: {}
      },
      rights: window.$gz.role.defaultRightsObject(),
      calendarHeight: 600,
      settingsDialog: false,
      newItemDialog: false,
      timeZoneName: window.$gz.locale.getResolvedTimeZoneName(),
      languageName: window.$gz.locale.getResolvedLanguage(),
      hour12: window.$gz.locale.getHour12(),
      formUserOptions: {}
    };
  },
  methods: {
    openObject: function(type, id) {
      window.$gz.eventBus.$emit("openobject", {
        type: type,
        id: id
      });
    },
    newItem(atype) {
      let 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.$store.state.userId,
                name: this.$store.state.userName
              }
            }
          });
          break;
        case this.$ay.ayt().Reminder:
          this.$router.push({
            name: "reminder-edit",
            params: {
              recordid: 0,
              add: {
                start: addStart,
                end: addEnd,
                userId: this.$store.state.userId,
                name: this.$store.state.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) {
      if (event.editable) {
        //My work around to disambiguate extending and clicking
        clearTimeout(this.dragTimeout);
        this.dragged = false;
        this.dragTimeout = setTimeout(() => {
          this.dragged = true;
        }, CLICK_DETECT_TIMEOUT); // Min delay to be regarded as extend instead of click, also affects click time to display more info, too short needs faster click

        //console.log("extendBottom setting extendEvent");
        this.extendEvent = event;
        this.createStart = event.start;
        this.extendOriginal = event.end;
      } else {
        //probably don't need this, was diagnosing new on click on locked items
        ////console.log("extendBottom not editable");
        // // this.dragged = false;
        // // this.extendEvent = null;
      }
    },
    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
      ////console.log("end drag extend");
      if (this.extendEvent && this.extendEvent.type == 0) {
        //console.log("end drag extend NEW");
        //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 {
        ////console.log("end drag extend MODIFY??");
        if (!this.dragged) {
          //we're here due to mouse up but it's not a drag or an extend so it's a More Info mouse up click so bail out now
          //console.log("end drag extend NOPE NOT MODIFY, MUST BE MOREINFO", {
          //   dragEvent: 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;
        }
        //console.log("end drag extend YES MODIFY");
        //MODIFY existing event, drag or extend
        if (this.dragEvent || this.extendEvent) {
          let param = { type: null, id: null, start: null, end: null };

          if (this.dragEvent) {
            // && this.dragged

            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);

            let res = await window.$gz.api.post("schedule/adjust", param);

            if (res.error) {
              this.formState.serverError = res.error;
              window.$gz.form.setErrorBoxErrors(this);
            } else {
            }
          } catch (error) {
            window.$gz.errorHandler.handleFormError(error, this);
          }
        }
      }
      this.dragTime = null;
      this.dragEvent = null;
      //console.log("endDragExtend setting extendEvent to null");
      this.extendEvent = null;
      this.createStart = null;
      this.extendOriginal = null;
    },
    cancelDrag() {
      if (this.extendEvent) {
        if (this.extendOriginal) {
          //console.log("cancelDrag setting extendEvent");
          this.extendEvent.end = this.extendOriginal;
        } else {
          const i = this.events.indexOf(this.extendEvent);
          if (i !== -1) {
            this.events.splice(i, 1);
          }
        }
      }
      //console.log("cancelDrag setting extendEvent to null");
      this.extendEvent = null;
      this.createStart = null;
      this.dragTime = null;
      this.dragEvent = null;
    },
    startDrag({ event }) {
      //# mouse down on an event triggers this call
      if (event) {
        if (event.editable) {
          //console.log("startDrag editable event: ", event);

          //My work around to disambiguate dragging and clicking
          clearTimeout(this.dragTimeout);
          this.dragged = false;
          this.dragTimeout = setTimeout(() => {
            this.dragged = true;
          }, CLICK_DETECT_TIMEOUT); // Min delay to be regarded as extend instead of click, also affects click time to display more info, too short needs faster click

          this.dragEvent = event;
          this.dragTime = null;
          this.extendOriginal = null;
        } else {
          //console.log("startDrag not editable");
          this.dragged = false;
          this.dragEvent = event;
          // this.extendEvent = null;
          this.dragTime = null;
        }
      }
    },
    mouseMoveDayView(tms) {
      //no event being dragged or exgtended?
      if (!this.dragEvent && !this.extendEvent) {
        return;
      }
      //console.log("mouseMoveDayView has event, processing...");
      const mouse = this.toTime(tms);
      if (this.dragEvent && this.dragTime !== null) {
        //console.log("mousemovedayview dragging");

        ////console.log("mouseMoveDAyView::dragging path ", {
        //   dragged: this.dragged,
        //   dragEvent: this.dragEvent,
        //   dragTime: this.dragTime
        // });
        //# 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) {
        //console.log("mouseMoveDAyView::extending path ", this.extendEvent);
        //# 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) {
          //console.log("startTime calculating this.dragTime");
          const start = this.dragEvent.start;
          this.dragTime = mouse - start;
        } else {
          //console.log("startTime AVOIDED calculating this.dragTime");
        }
      } else {
        //# DAY VIEW CREATE START EVENT
        this.createStart = this.roundTime(mouse);
        //console.log("startTime setting extendEvent");
        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();
    },
    diagInfo() {
      if (this.$refs.calendar) {
        return (
          "cal" +
          JSON.stringify({
            start: this.$refs.calendar.start,
            end: this.$refs.calendar.end,

            focus: this.focus,
            firstInterval: this.$refs.calendar.firstInterval
          })
        );
      } else {
        return "no calendar";
      }
    },
    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 }) {
      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({ nativeEvent, event }) {
      //workaround to disambiguate drag click from view more info click
      if (this.dragged) {
        return;
      }
      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) {
        let res = await window.$gz.api.get(route);
        if (!res.error) {
          this.evInfo = res.data;
        }
      }

      const open = () => {
        this.selectedEvent = event;
        this.selectedElement = nativeEvent.target;
        requestAnimationFrame(() =>
          requestAnimationFrame(() => (this.moreInfoDialog = true))
        );
      };

      if (this.moreInfoDialog) {
        this.moreInfoDialog = false;
        requestAnimationFrame(() => requestAnimationFrame(() => open()));
      } else {
        open();
      }

      nativeEvent.stopPropagation();
    },
    async fetchEvents({ start, end }) {
      console.log("Fetching events");
      try {
        window.$gz.form.deleteAllErrorBoxErrors(this);
        let res = await window.$gz.api.post("schedule/personal", {
          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
        });

        if (res.error) {
          this.formState.serverError = res.error;
          window.$gz.form.setErrorBoxErrors(this);
        } else {
          this.events = res.data.map(x => {
            return {
              ...x,
              start: window.$gz.locale.utcDateToScheduleCompatibleFormatLocalized(
                x.start,
                this.timeZoneName
              ),
              end: window.$gz.locale.utcDateToScheduleCompatibleFormatLocalized(
                x.end,
                this.timeZoneName
              )
            };
          });
        }
      } catch (error) {
        window.$gz.errorHandler.handleFormError(error, this);
      }
    }
    //eom
  }
};

/////////////////////////////
//
//
async function clickHandler(menuItem) {
  if (!menuItem) {
    return;
  }
  let m = window.$gz.menu.parseMenuItem(menuItem);
  if (m.owner == FORM_KEY && !m.disabled) {
    switch (m.key) {
      // case "report":
      //   let 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.setLastReport(FORM_KEY, res);
      //   generateMenu(m.vm);
      //   break;
      case "WorkOrderItemScheduledUserList":
        m.vm.$router.push({
          name: "svc-workorder-item-scheduled-users",
          params: {
            aType: window.$gz.type.User,
            objectId: m.vm.$store.state.userId,
            name: m.vm.$store.state.userName
          }
        });
        break;
      case "WorkOrderItemLaborList":
        m.vm.$router.push({
          name: "svc-workorder-item-labors",
          params: {
            aType: window.$gz.type.User,
            objectId: m.vm.$store.state.userId,
            name: m.vm.$store.state.userName
          }
        });
        break;

      default:
        window.$gz.eventBus.$emit(
          "notify-warning",
          FORM_KEY + "::context click: [" + m.key + "]"
        );
    }
  }
}

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

  // //REPORTS
  // //Report not Print, print is a further option
  // menuOptions.menuItems.push({
  //   title: "Report",
  //   icon: "$ayiFileAlt",
  //   key: FORM_KEY + ":report",
  //   vm: vm
  // });

  // //get last report selected
  // let 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
  //   });
  // }

  // if (vm.rights.change) {
  //   menuOptions.menuItems.push({
  //     title: "New",
  //     icon: "$ayiPlus",
  //     key: FORM_KEY + ":new",
  //     vm: vm
  //   });
  // }

  if (vm.$store.getters.isScheduleableUser) {
    menuOptions.menuItems.push({ divider: true, inset: false });

    menuOptions.menuItems.push({
      title: "WorkOrderItemScheduledUserList",
      icon: "$ayiUserClock",
      key: FORM_KEY + ":WorkOrderItemScheduledUserList",
      vm: vm
    });
    menuOptions.menuItems.push({
      title: "WorkOrderItemLaborList",
      icon: "$ayiHammer",
      key: FORM_KEY + ":WorkOrderItemLaborList",
      vm: vm
    });
    //--- /show all ---
  }
  menuOptions.menuItems.push({ divider: true, inset: false });

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

/////////////////////////////////
//
//
async function initForm(vm) {
  await fetchTranslatedText(vm);
  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) {
  let 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) {
  let 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) {
      console.log("getFormUserOptions null setting default");
      //make a default
      vm.formUserOptions = {
        firstTime: "00:00",
        wisuColorSource: 4,
        wisu: true,
        reviews: true,
        reminders: true
      };
    } else {
      vm.formUserOptions = res.data;
    }
  }
}

////////////////////
//
async function saveFormUserOptions(vm) {
  let res = await window.$gz.api.upsert(
    "form-user-options",
    vm.formUserOptions
  );

  if (res.error) {
    vm.formState.serverError = res.error;
    window.$gz.form.setErrorBoxErrors(vm);
  }
}

//////////////////////////////////////////////////////////
//
// Ensures UI translated text is available
//
async function fetchTranslatedText(vm) {
  await window.$gz.translation.cacheTranslations([
    "DateRangeToday",
    "ScheduleMonth",
    "ScheduleDay",
    "ScheduleWeek",
    "Schedule4Day",
    "WorkOrder",
    "Reminder",
    "Review",
    "DashboardScheduled",
    "WorkOrderItemPriorityID",
    "WorkOrderItemSummary",
    "WorkOrderStatus",
    "WorkOrderItemScheduledUserEstimatedQuantity",
    "WorkOrderItemScheduledUserServiceRateID",
    "WorkOrderItemTags"
  ]);
}
</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>
