<template>
  <div class="row full-width">
    <vis-timeline
      ref="timeline"
      class="col"
      :items="itemsTransformed"
      :groups="groups"
      :options="options"
      @changed="graphLoaded = true"
      @select="onSelect"
      @click="onClick"
    />
    <div v-if="fancyTooltips && graphLoaded">
      <q-tooltip
        v-for="item in itemsTransformed"
        :key="item.key"
        :target="`#timeline-flag-${item.id}`"
        class="bg-tooltips text-black q-pa-md shadow-1 timeline-tooltip"
        anchor="center right"
        self="center left"
      >
        <div class="text-h6 text-bold">
          {{ item.title }}
        </div>
        <div v-if="item.subtitle" class="text-h6 text-weight-light">
          {{ item.subtitle }}
        </div>
        <p class="q-mt-xs text-body1 text-weight-light">
          {{ `${formatDate(item.start)} - ${item.end ? formatDate(item.end): 'present'}` }}
        </p>
        <p v-if="item.description" class="q-mt-xs text-body1 text-weight-light">
          {{ item.description }}
        </p>
      </q-tooltip>
    </div>
    <q-icon v-if="showKey" class="col-auto q-pa-sm" name="fal fa-question-circle">
      <q-tooltip class="bg-white text-black q-pa-md shadow-1" anchor="center left" self="top right">
        <div class="row q-gutter-md q-pa-xs">
          <div class="key-square bg-employment" />
          <div class="text-body1">
            Job
          </div>
        </div>
        <div class="row q-gutter-md q-pa-xs">
          <div class="key-square bg-hobby" />
          <div class="text-body1">
            Hobby
          </div>
        </div>
        <div class="row q-gutter-md q-pa-xs">
          <div class="key-square bg-education" />
          <div class="text-body1">
            Education
          </div>
        </div>
      </q-tooltip>
    </q-icon>
  </div>
</template>

<script>
import VisTimeline from "../vis-timeline/VisTimeline";
import "vis-timeline/dist/vis-timeline-graph2d.css";
import moment from "moment";

const placeholderClass = "placeholder";

export default {
  components: {
    VisTimeline,
  },
  props: {
    items: { // id, kind, importance (1..10), start, end -- TODO: create proper type after TypeScript conversion
      type: Array,
      required: true,
    },
    readonly: {
      type: Boolean,
      default: false,
    },
    // Currently does not work if component is editable or flags on the timeline are grouped
    fancyTooltips: {
      type: Boolean,
      default: false,
    },
    showKey: {
      type: Boolean,
      default: false,
    },
  },
  emits: ["click", "select"],
  data() {
    return {
      graphLoaded: false,
      windowHeight: 0,
      isSmallScreen: window.innerHeight < 660,
    };
  },
  computed: {
    options() {
      return {
        type: "box",
        editable: false,
        align: "left",
        groupHeightMode: "fixed",
        width: "100%",
        stack: false,
        selectable: !this.readonly,
        clickToUse: this.isSmallScreen,
        zoomMax: 3155760000000, // 100 years in milliseconds
        cluster: {
          showStipes: true,
          titleTemplate: "Double-click or zoom in to see the individual events.",
          clusterCriteria: (a, b) => a.className !== placeholderClass && b.className !== placeholderClass,
        },
        start: this.items && this.items.length > 0 ? moment(this.getEarliestDate()).add(-1, "months") : new Date(),
        end: moment().add(3, "months"),
        showTooltips: !this.fancyTooltips,
        template: (itemData, element, data) => {
          if (data.isCluster) {
            return `<span class="cluster-header">${data.items.length} events</span>`;
          } else {
            return `<div class="flag ${data.content}" id="timeline-flag-${data.id}"></div>`;
          }
        },
        order: (a, b) => a.start - b.start,
        xss: {
          disabled: false,
          filterOptions: {
            whiteList: {
              span: ["class"],
              div: ["class", "id"],
            },
          },
        },
      };
    },
    itemsTransformed() {
      const placeholderDate = moment().add(2, "months");

      const placeholders = [...Array(10).keys()].map(x => ({
        id: `placeholder-${x}`,
        group: x,
        content: "",
        start: placeholderDate,
        end: placeholderDate,
        className: placeholderClass,
      }));

      const transformedItems = this.items.map(x => ({
        id: x.id,
        title: x.title,
        subtitle: x.subtitle,
        description: x.description,
        group: x.importance,
        content: x.kind,
        start: x.start,
        end: x.end || new Date(),
        key: Math.random(), // a hack to stop tooltips on existing flags not working when a new flag is added -- this forces Vue to re-render affected components
      }));

      return [...placeholders, ...transformedItems];
    },
    groups() {
      return [...Array(10).keys()].reverse().map(x => (
        {
          id: x + 1,
          content: x + 1,
        }
      ));
    },
  },
  watch: {
    windowHeight(newHeight, oldHeight) {
      if (newHeight < 660) this.isSmallScreen = true;
      else this.isSmallScreen = false;
    },
    items: {
      handler: function (value, oldValue) {
        this.$refs.timeline.setData({
          groups: this.groups,
          items: this.itemsTransformed,
        });
      },
      deep: true,
    },
  },
  mounted() {
    this.$nextTick(() => {
      window.addEventListener("resize", this.onResize);
    });
  },
  beforeUnmount() {
    window.removeEventListener("resize", this.onResize);
  },
  methods: {
    getEarliestDate(items) {
      return this.items && this.items.map(x => x.start).reduce((a, b) => a < b ? a : b);
    },
    formatDate(value) {
      return moment(String(value)).format("DD MMMM YYYY");
    },
    onResize() {
      this.windowHeight = window.innerHeight;
    },
    onChanged() {
      this.graphLoaded = true;
    },
    onClick(event) {
      this.$emit("click", event);
    },
    onSelect(event) {
      this.$emit("select", event);
    },
  },
};
</script>
