<template>
  <div>
    <v-sheet height="64">
      <v-toolbar flat>

        <v-menu bottom right>
          <template v-slot:activator="{ on, attrs }">
            <v-btn
              outlined
              color="grey darken-2"
              v-bind="attrs"
              v-on="on"
            >
              <span>Go to</span>
              <v-icon right>mdi-menu-down</v-icon>
            </v-btn>
          </template>
          <v-list>
            <v-list-item @click="setFirst">
              <v-list-item-title>First sequence</v-list-item-title>
            </v-list-item>
            <v-list-item @click="setLast">
              <v-list-item-title>Last sequence</v-list-item-title>
            </v-list-item>
            <v-list-item @click="setToday">
              <v-list-item-title>Today</v-list-item-title>
            </v-list-item>
          </v-list>
        </v-menu>


        <v-btn fab text small color="grey darken-2" @click="prev">
          <v-icon small>mdi-chevron-left</v-icon>
        </v-btn>
        <v-btn fab text small color="grey darken-2" @click="next">
          <v-icon small>mdi-chevron-right</v-icon>
        </v-btn>
        <v-toolbar-title v-if="$refs.calendar">
          {{ $refs.calendar.title }}

        <span
          class="secondary--text"
          style="font-size:small;"
        >
        ({{downloadableItemCount}} log entries)
        </span>
        </v-toolbar-title>

          <v-menu class="ml-5" v-if="calendarDates">
            <template v-slot:activator="{on, attrs}">
                <v-btn
                  class="ml-5"
                  small
                  :title="`Download events for the period ${calendarDates.start} ‒ ${calendarDates.end}`"
                  v-on="on"
                  v-bind="attrs"
                >
                  <span class="d-none d-lg-inline">Download as…</span>
                  <v-icon right small>mdi-cloud-download</v-icon>
                </v-btn>
            </template>

            <v-list>
              <v-list-item
                :href="downloadUrl({mime: 'application/vnd.seis+json', filename: `event-log-${calendarDates.start}-${calendarDates.end}-multiseis.json`})"
                title="Download as a Multiseis-compatible Seis+JSON file."
              >Seis+JSON</v-list-item>
              <!-- Not yet supported
              <v-list-item
                :href="downloadUrl({mime: 'application/geo+json'})"
                title="Download as a QGIS-compatible GeoJSON file"
              >GeoJSON</v-list-item>
              -->
              <v-list-item
                :href="downloadUrl({mime: 'application/json', filename: `event-log-${calendarDates.start}-${calendarDates.end}.json`})"
                title="Download as a generic JSON file"
              >JSON</v-list-item>
              <v-list-item
                :href="downloadUrl({mime: 'application/yaml', filename: `event-log-${calendarDates.start}-${calendarDates.end}.yaml`})"
                title="Download as a YAML file"
              >YAML</v-list-item>
              <v-list-item
                :href="downloadUrl({mime: 'text/csv', sortBy: 'tstamp', sortDesc: false, filename: `event-log-${calendarDates.start}-${calendarDates.end}.csv`})"
                title="Download as Comma Separated Values file"
              >CSV</v-list-item>
              <!-- Not yet supportd
              <v-list-item
                :href="downloadUrl({mime: 'text/html'})"
                title="Download as an HTML formatted file"
              >HTML</v-list-item>
              <v-list-item
                :href="downloadUrl({mime: 'application/pdf'})"
                title="Download as a Portable Document File"
              >PDF</v-list-item>
              -->
            </v-list>
          </v-menu>

        <v-spacer></v-spacer>
        <v-btn v-if="categoriesAvailable"
          small
          class="mx-4"
          v-model="useCategories"
          @click="useCategories = !useCategories"
        >Labels {{useCategories ? "On" : "Off"}}</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>{{ typeLabel }}</span>
              <v-icon right>mdi-menu-down</v-icon>
            </v-btn>
          </template>
          <v-list>
            <v-list-item @click="type = 'day'">
              <v-list-item-title>Day</v-list-item-title>
            </v-list-item>
            <v-list-item @click="type = 'week'">
              <v-list-item-title>Week</v-list-item-title>
            </v-list-item>
            <v-list-item @click="type = 'month'">
              <v-list-item-title>Month</v-list-item-title>
            </v-list-item>
            <v-list-item @click="type = '4day'">
              <v-list-item-title>4 days</v-list-item-title>
            </v-list-item>
          </v-list>
        </v-menu>
      </v-toolbar>
    </v-sheet>
    <v-sheet>
      <v-calendar
        ref="calendar"
        v-model="focus"
        :events="items"
        :event-color="getEventColour"
        color="primary"
        :type="view"
        :locale-first-day-of-year="4"
        :weekdays="weekdays"
        :show-week="true"
        :category-days="categoryDays"
        :categories="categories"
        @click:date="showLogForDate"
        @click:event="showLogForEvent"
        @change="setSpan"
      >
        <template v-slot:event="{ event }">
            <div style="height:100%;overflow:scroll;" v-html="event.name"></div>
        </template>
      </v-calendar>
    </v-sheet>
  </div>
</template>

<script>
import { mapActions, mapGetters } from 'vuex';

export default {
  name: "Calendar",

  data () {
    return {
      weekdays: [1, 2, 3, 4, 5, 6, 0],
      type: "week",
      focus: "",
      items: [],
      useCategories: false,
      span: {},
      options: {
        sortBy: "sequence"
      }
    };
  },

  computed: {
    typeLabel () {
      const labels = {
        month: 'Month',
        week: 'Week',
        day: 'Day',
        '4day': '4 Days',
      };

      return labels[this.type];
    },

    view () {
      return this.useCategories ? "category" : this.type;
    },

    categoriesAvailable () {
      return this.type == "day" || this.type == "4day";
    },

    categoryDays () {
      if (this.useCategories) {
        const days = {
          month: 30,
          week: 7,
          "4day": 4,
          day: 1
        };

        return days[this.type];
      }
    },

    visibleItems () {
      return this.items.filter(i => {
        const end = i.end ?? i.start;
        if (i.start > this.span.end) {
          return false;
        }
        if (end < this.span.start) {
          return false;
        }
        return true;
      });
    },

    categories () {
      return [...new Set(this.visibleItems.map(i => i.category ?? "General"))];
    },

    calendarDates () {
      // The this.items.length reference is only needed to force recalculation
      // of this computed property, as this.$refs is not reactive.
      // https://github.com/vuejs/vue/issues/3842
      if (this.items.length && this.$refs.calendar) {
        return {
          start: this.$refs.calendar.renderProps.start.date,
          end: this.$refs.calendar.renderProps.end.date
        }
      }
    },

    downloadableItemCount () {
      return this.events.filter(i => i.tstamp.substr(0, 10) >= this.calendarDates?.start &&
        i.tstamp.substr(0, 10) <= this.calendarDates?.end).length;
    },

    ...mapGetters(['sequencesLoading', 'sequences', 'events'])
  },

  watch: {

    sequences () {
      const isFirstLoad = !this.items.length;

      this.getEvents();

      if (isFirstLoad) {
        this.setLast();
      }

    },

    events () {
      const isFirstLoad = !this.items.length;

      this.getEvents();

      if (isFirstLoad) {
        this.setLast();
      }

    },

    type () {
      this.getEvents();
    },

    categoriesAvailable (value) {
      if (!value) {
        this.useCategories = false;
      }
    }

  },

  methods: {

    async getEvents () {
      const sequences = this.sequences.map(s => {
        const e = {};
        e.routerLink = { name: "logBySequence", params: { sequence: s.sequence } };
        e.start = new Date(s.ts0);
        e.end = new Date(s.ts1);
        e.timed = true;
        e.colour = "orange";
        e.name = `<b>Sequence ${s.sequence}</b><br/>Line ${s.line}<br/><abbr title="Shotpoints">SP</abbr> ${s.fgsp ?? s.fsp}‒${s.lgsp ?? s.lsp}`;
        e.category = "Sequence"
        return e;
      });

      const lineChanges = this.events.filter(i => i.meta?.["*ReportLineChangeTime*"]?.value && i.meta?.["*ReportLineChangeTime*"]?.type != "excess").map(i => {
        const e = {};
        const duration = i.meta?.["*ReportLineChangeTime*"]?.value;
        e.end = new Date(i.tstamp);
        e.start = new Date(e.end - duration);
        e.timed = true;
        e.colour = "pink";
        e.name = "Line change";
        e.category = "Production"
        return e;
      });

      const excludedLabels = [ "FSP", "FGSP", "LSP", "LGSP", "QC" ];
      const otherEvents = this.events.filter(i => !excludedLabels.some(l => i.labels.includes(l))).map(i => {
        const e = {};
        e.start = new Date(i.tstamp);
        e.colour = "brown";
        e.timed = true;
        e.name = this.$options.filters.markdownInline(i.remarks);
        e.category = i.labels[0];
        return e;
      });

      this.items = [...sequences];

      if (this.type == "day" || this.type == "4day") {
        this.items.push(...lineChanges, ...otherEvents);
      }
    },

    getEventColour (event) {
      return event.colour;
    },

    setToday () {
      this.focus = "";
    },

    setFirst () {
      if (this.items.length) {
        this.focus = this.items[this.items.length-1].start;
      }
    },

    setLast () {
      if (this.items.length) {
        this.focus = this.items[0].start;
      }
    },

    prev () {
      this.$refs.calendar.prev()
    },

    next () {
      this.$refs.calendar.next()
    },

    showLogForDate ({ date }) {
      this.$router.push({name: "logByDate", params: {date0: date}});
    },

    showLogForEvent ({event}) {
      if (event.routerLink) {
        this.$router.push(event.routerLink);
      }
    },

    setSpan (span) {
      this.span = {
        start: new Date(span.start.date),
        end:   new Date((new Date(span.end.date)).valueOf() + 86400000)
      };
    },

    downloadUrl (qry) {
      if (this.calendarDates) {
        const url = new URL(`/api/project/${this.$route.params.project}/event`, document.location.href);
        for (const key in qry) {
          url.searchParams.set(key, qry[key]);
        }
        url.searchParams.set("date0", this.calendarDates.start);
        url.searchParams.set("date1", this.calendarDates.end);
        return url.toString();
      }
    },


    ...mapActions(["api"])

  },

  async mounted () {
    await this.getEvents();
    this.setLast();
  }
}

</script>
