<template>
  <infinite-scrolling-date-sorted-c-r-u-d-iterator
    i18n-key="alsijil.coursebook"
    :gql-query="gqlQuery"
    :gql-additional-query-args="gqlQueryArgs"
    :enable-create="false"
    :enable-edit="false"
    :elevated="false"
    @lastQuery="lastQuery = $event"
    ref="iterator"
    fixed-header
    disable-pagination
    hide-default-footer
    use-deep-search
  >
    <template #additionalActions="{ attrs, on }">
      <coursebook-filters v-model="filters" />
      <absence-reason-buttons
        v-if="pageType === 'absences' && selectedParticipations.length"
        allow-empty
        empty-value="present"
      />
    </template>

    <template #item="{ item, lastQuery }">
      <component :is="itemComponent" :documentation="item" :affectedQuery="lastQuery" @select="addSelectedParticipation" @deselect="removeSelectedParticipation" />
    </template>

    <template #loading>
      <coursebook-loader :number-of-days="10" :number-of-docs="5" />
    </template>

    <template #itemLoader>
      <coursebook-loader />
    </template>

    <template #no-data>
      <CoursebookEmptyMessage icon="mdi-book-off-outline">
        {{ $t("alsijil.coursebook.no_data") }}
      </CoursebookEmptyMessage>
    </template>

    <template #no-results>
      <CoursebookEmptyMessage icon="mdi-book-alert-outline">
        {{
          $t("alsijil.coursebook.no_results", { search: $refs.iterator.search })
        }}
      </CoursebookEmptyMessage>
    </template>
  </infinite-scrolling-date-sorted-c-r-u-d-iterator>
</template>

<script>
import InfiniteScrollingDateSortedCRUDIterator from "aleksis.core/components/generic/InfiniteScrollingDateSortedCRUDIterator.vue";
import { DateTime, Interval } from "luxon";
import { documentationsForCoursebook } from "./coursebook.graphql";
import AbsenceReasonButtons from "aleksis.apps.kolego/components/AbsenceReasonButtons.vue";
import CoursebookFilters from "./CoursebookFilters.vue";
import CoursebookLoader from "./CoursebookLoader.vue";
import CoursebookEmptyMessage from "./CoursebookEmptyMessage.vue";
import DocumentationModal from "./documentation/DocumentationModal.vue";
import DocumentationAbsencesModal from "./absences/DocumentationAbsencesModal.vue";

export default {
  name: "Coursebook",
  components: {
    AbsenceReasonButtons,
    CoursebookEmptyMessage,
    CoursebookFilters,
    CoursebookLoader,
    DocumentationModal,
    DocumentationAbsencesModal,
    InfiniteScrollingDateSortedCRUDIterator,
  },
  props: {
    filterType: {
      type: String,
      required: true,
    },
    objId: {
      type: [Number, String],
      required: false,
      default: null,
    },
    objType: {
      type: String,
      required: false,
      default: null,
    },
    pageType: {
      type: String,
      required: false,
      default: "documentations",
    },
    /**
     * Number of consecutive to load at once
     * This number of days is initially loaded and loaded
     * incrementally while scrolling.
     */
    dayIncrement: {
      type: Number,
      required: false,
      default: 7,
    },
    /**
     * Margin from coursebook list to top of viewport in pixels
     */
    topMargin: {
      type: Number,
      required: false,
      default: 165,
    },
  },
  data() {
    return {
      gqlQuery: documentationsForCoursebook,
      lastQuery: null,
      dateStart: "",
      dateEnd: "",
      // Placeholder values while query isn't completed yet
      groups: [],
      courses: [],
      incomplete: false,
      ready: false,
      initDate: false,
      currentDate: "",
      hashUpdater: false,
      selectedParticipations: [],
    };
  },
  computed: {
    // Assertion: Should only fire on page load or selection change.
    //            Resets date range.
    gqlQueryArgs() {
      return {
        own: this.filterType === "all" ? false : true,
        objId: this.objId ? Number(this.objId) : undefined,
        objType: this.objType?.toUpperCase(),
        dateStart: this.dateStart,
        dateEnd: this.dateEnd,
        incomplete: !!this.incomplete,
      };
    },
    filters: {
      get() {
        return {
          objType: this.objType,
          objId: this.objId,
          filterType: this.filterType,
          incomplete: this.incomplete,
          pageType: this.pageType,
        };
      },
      set(selectedFilters) {
        if (Object.hasOwn(selectedFilters, "incomplete")) {
          this.incomplete = selectedFilters.incomplete;
        } else if (
          Object.hasOwn(selectedFilters, "filterType") ||
          Object.hasOwn(selectedFilters, "objId") ||
          Object.hasOwn(selectedFilters, "objType") ||
          Object.hasOwn(selectedFilters, "pageType")
        ) {
          this.$router.push({
            name: "alsijil.coursebook",
            params: {
              filterType: selectedFilters.filterType
                ? selectedFilters.filterType
                : this.filterType,
              objType: selectedFilters.objType,
              objId: selectedFilters.objId,
              pageType: selectedFilters.pageType
                ? selectedFilters.pageType
                : this.pageType,
            },
            hash: this.$route.hash,
          });
          // computed should not have side effects
          // but this was actually done before filters was refactored into
          // its own component
          this.$refs.iterator.resetDate();
          // might skip query until both set = atomic
        }
      },
    },
    itemComponent() {
      if (this.pageType === 'documentations') {
        return "DocumentationModal";
      } else {
        return "DocumentationAbsencesModal";
      }
    },
  },
  methods: {
    addSelectedParticipation(participation) {
      this.selectedParticipations = [...new Set([...this.selectedParticipations, participation])];
    },
    removeSelectedParticipation(participation) {
      const index = this.selectedParticipations.indexOf(participation);
      if (index>=0) {
        this.selectedParticipations.splice(index, 1);
      }
    }
  },
};
</script>

<style>
.max-width {
  max-width: 25rem;
}
</style>