<template>
  <navigation v-model="show" :options="navOption">
    <div class="page" v-show="show == 'benevole'">
      <data-table
        class="data-table"
        title="Liste des bénévoles"
        :data="data"
        :clickable="true"
        :loadingAnimation="loading"
        :exportable="false"
        locale="fr"
        @row-click="onRowClick"
        :customButtons="customButton"
      ></data-table>
      <editeur-benevole
        :benevole="currentBenevole"
        @create="createBenevole"
        @delete="deleteBenevole"
      />
      <input type="file" ref="loadcsv" @change="importBenevoleTemplate" style="display: none" />
    </div>
    <editeur-questionnaire
      v-if="show == 'questionnaire'"
      :competences="competenceList"
      :uuid="uuid"
    />
    <manage-registration v-if="show == 'inscriptions'" />
    <filter-panel
      ref="filter"
      :data="benevoleForFilter"
      title="Filtrer les bénévoles"
      @filterChange="updateList($event)"
      :filters="filters"
    />
  </navigation>
</template>

<script lang="ts">
import Competence from "@/models/Competence";
import EditeurBenevole from "@/components/EditeurBenevole.vue";
import FilterPanel, { FilterParam } from "@/components/Utils/FilteringPanel.vue";
import EditeurQuestionnaire from "@/components/EditeurQuestionnaire.vue";
import ManageRegistration from "@/components/Utils/ManageRegistration.vue";
import Navigation from "@/components/Utils/NavigationPanel.vue";
import DataTable, {
  CustomButton,
  DataTableColumn,
  DataTableData,
} from "@/components/Utils/DataTable.vue";
import { defineComponent } from "vue";
import { MutationTypes } from "@/store/Mutations";
import Benevole from "@/models/Benevole";
import csv from "@/utils/csv";
import dayjs from "dayjs";
import Toast from "@/utils/Toast";

const csvDefaultcolumn = "id,prenom,nom,telephone,email,commentaire";
const navOption = [
  { id: "benevole", title: "Bénévoles" },
  { id: "questionnaire", title: "Gestion du questionnaire" },
  { id: "inscriptions", title: "Validations des inscriptions" },
];
const filters: Array<FilterParam> = [
  {
    name: "Préference & compétences",
    type: "category",
    key: "competenceIdList",
    placeholder: "Selectionner une compétence",
  },
];
type filterObject = {
  id: number;
  competenceIdList: Array<string>;
};
type BenevoleTableObject = {
  id: number;
  name: string;
  surname: string;
  fanfare: string;
  creneauLength: number;
};
const columns: Array<DataTableColumn<BenevoleTableObject>> = [
  {
    label: "Prénom",
    field: "name",
    numeric: false,
    html: false,
    class: "overflow-cell",
  },
  {
    label: "Nom",
    field: "surname",
    numeric: false,
    html: false,
    class: "overflow-cell",
  },
  {
    label: "Fanfare",
    field: "fanfare",
    numeric: false,
    html: false,
    class: "fitwidth",
    export: "fanfare",
  },
  {
    label: "Duree créneau(h)",
    field: "creneauLength",
    numeric: true,
    html: false,
    class: "fitwidth",
    export: "creneauLength",
  },
];
export default defineComponent({
  name: "EditeurCreneau",
  components: {
    DataTable,
    EditeurBenevole,
    ManageRegistration,
    EditeurQuestionnaire,
    Navigation,
    FilterPanel,
  },
  data: () => ({
    navOption,
    show: "benevole",
    columns,
    currentBenevole: undefined as Benevole | undefined,
    loading: true,
    customButton: [] as Array<CustomButton>,
    benevoleList: [] as Array<Benevole>,
    filters,
  }),
  computed: {
    uuid(): string {
      return this.$store.state.evenement.uuid;
    },
    csvInputElt(): HTMLInputElement {
      return this.$refs.loadcsv as HTMLInputElement;
    },
    competenceList(): Array<Competence> {
      return this.$store.state.competenceList;
    },
    fanfareList(): Array<Competence> {
      return this.competenceList.filter((o) => o.name.startsWith("Fanfare"));
    },
    rawBenevoleList(): Array<Benevole> {
      return this.$store.state.benevoleList;
    },
    benevoleForFilter(): Array<filterObject> {
      return this.rawBenevoleList.map((b: Benevole) => {
        return {
          id: b.id,
          competenceIdList: b.competenceIdList.map(
            (id) => this.competenceList.find((o) => o.id == id)?.name ?? ""
          ),
        };
      });
    },
    data(): DataTableData<BenevoleTableObject> {
      return {
        items: this.benevoleList.map((b) => {
          return {
            id: b.id,
            name: b.name,
            surname: b.surname,
            fanfare: this.getFanfareForBenevole(b),
            creneauLength: this.getBenevoleTotalLength(b),
          };
        }),
        columns: this.columns,
      };
    },
  },
  watch: {
    rawBenevoleList() {
      this.benevoleList = this.rawBenevoleList;
      (this.$refs.filter as typeof FilterPanel).reset();
    },
  },
  methods: {
    openFilter() {
      (this.$refs.filter as typeof FilterPanel).open();
    },
    updateList(l: Array<filterObject>) {
      const ids = l.map((o) => o.id);
      this.benevoleList = this.rawBenevoleList.filter((b) => ids.includes(b.id));
    },
    getFanfareForBenevole(benevole: Benevole): string {
      if (benevole.competenceIdList.length == 0) {
        return "Exte";
      } else {
        const fanfare = this.fanfareList
          .filter((o) => benevole.competenceIdList.indexOf(o.id) > -1)
          .map((o) => o.name.substring(8))
          .join(", ");
        return fanfare ? fanfare : "Exte";
      }
    },
    getBenevoleTotalLength(benevole: Benevole): number {
      return this.$store.state.creneauList
        .filter((c) => c.benevoleIdList.indexOf(benevole.id) > -1)
        .reduce((acc, creneau) => acc + creneau.durationH, 0);
    },
    createBenevole() {
      const temp = Benevole.fromObject({ name: "Benevole i", surname: "" });
      this.$store.commit(MutationTypes.addBenevole, temp);
      this.currentBenevole = temp;
    },
    deleteBenevole(payload: Benevole) {
      this.$store.commit(MutationTypes.removeBenevole, payload.id);
      this.currentBenevole = undefined;
    },
    onRowClick(row: { id: number }) {
      this.currentBenevole = this.$store.getters.getBenevoleById(row.id);
    },
    getImportTemplate() {
      const competences = this.$store.state.competenceList;
      let csvContent = `${csvDefaultcolumn},${competences.map((c) => c.name).join(",")}\r\n`;
      this.benevoleList.forEach(
        (b) =>
          (csvContent +=
            [
              b.id,
              b.name,
              b.surname,
              b.phone,
              b.email,
              b.comment,
              ...competences.map((c) => (b.competenceIdList.includes(c.id) ? "X" : "")),
            ].join(",") + "\r\n")
      );
      const dummy = document.createElement("a");
      dummy.href = "data:text/csv;charset=utf-8, " + encodeURI(csvContent);
      dummy.download = "Benevole-import" + dayjs().format("-YYYY-MM-DD-hh-mm-ss[.csv]");
      document.body.appendChild(dummy);
      dummy.click();
    },
    importBenevoleTemplate() {
      const fs = this.csvInputElt.files;
      if (fs && fs.length > 0) {
        let reader = new FileReader();
        reader.readAsText(fs[0]);
        reader.onload = () => {
          let csvtxt = reader.result as string;
          const arr = csv.toArray(csvtxt);
          const defaultKey = csvDefaultcolumn.split(",");
          const competencesMap: { [k: string]: Competence } = {};
          for (let key of arr[0]) {
            if (!defaultKey.includes(key)) {
              key = key.trim();
              // check if a competence exist with this name
              let c = this.competenceList.find((c) => c.name == key);
              if (c == undefined) {
                Toast({ html: "Compétence inconnue: " + key, classes: "warning" });
                c = Competence.fromObject({ name: key, description: "" });
                this.$store.commit(MutationTypes.addConstraint, c);
              }
              if (c) {
                competencesMap[key] = c;
              }
            }
          }
          const objectList = csv.toObject(csvtxt);
          for (let item of objectList) {
            const id = parseInt(item.id);

            let b: Benevole | undefined = undefined;
            if (id) b = this.$store.getters.getBenevoleById(id);
            if (b == undefined) {
              b = Benevole.fromObject({
                id: id ?? undefined,
                name: item.prenom,
                surname: item.nom,
                phone: item.telephone,
                email: item.email,
                comment: item.commentaire,
              });
              this.$store.commit(MutationTypes.addBenevole, b);
            } else {
              let map: Array<{ k: string; v: keyof Benevole }> = [
                { k: "prenom", v: "name" },
                { k: "nom", v: "surname" },
                { k: "telephone", v: "phone" },
                { k: "commentaire", v: "comment" },
                { k: "email", v: "email" },
              ];
              map.forEach((o) =>
                this.$store.commit(MutationTypes.editBenevole, {
                  id: (b as Benevole).id,
                  field: o.v,
                  value: item[o.k],
                })
              );
            }
            const competenceIdList = [];
            for (let key in competencesMap) {
              if (item[key].trim() == "X") {
                competenceIdList.push(competencesMap[key].id);
              }
            }
            this.$store.commit(MutationTypes.editBenevole, {
              id: b.id,
              field: "competenceIdList",
              value: competenceIdList,
            });
          }
        };
      }
    },
  },
  mounted() {
    this.loading = false;
    this.customButton.push({ icon: "filter_alt", hide: false, onclick: this.openFilter });
    this.customButton.push({ icon: "file_download", hide: false, onclick: this.getImportTemplate });
    this.customButton.push({
      icon: "file_upload",
      hide: false,
      onclick: () => {
        this.csvInputElt.click();
      },
    });
    this.benevoleList = this.rawBenevoleList;
  },
});
</script>

<style scoped>
.page {
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 1100px;
  gap: 16px;
}
.data-table {
  width: 100%;
  height: min-content;
}
@media (min-width: 600px) {
  .page {
    flex-direction: row;
  }
  .data-table {
    width: calc(100% - 432px);
  }
}
@media (min-width: 1200px) {
  .page {
    margin-top: 8px;
  }
}
</style>
