<template>
  <DataTable :columnDefs="columnDefs"
             tableId="ProjectList"
             :dataUrl="dataSource"
             :reloadingTable="reloadingTable"
             :toolbarActions="toolbarActions"
             :actionsUrl="actionsUrl"
             :activePageUrl="activePageUrl"
             :archivedPageUrl="archivedPageUrl"
             :currentViewMode="currentViewMode"
             scrollMode="infinite"
             :filters="filters"
             :tableOnly="true"
             @tableReloaded="reloadingTable = false"
             @comments="openComments"
             @archive="archive"
             @restore="restore"
             @edit="edit"
             @create="create"
             @create_folder="createFolder"
             @delete_folders="deleteFolder"
             @export="exportProjects"
             @showDescription="showDescription"
             @changeStatus="changeStatus"
             @changeSuperviser="changeSuperviser"
             @move="move"
             @access="access"
             @updateDueDate="updateDueDate"
             @updateStartDate="updateStartDate"
             @updateFavorite="updateFavorite"
  >
    <template #card="data">
      <ProjectCard :params="data.params" :dtComponent="data.dtComponent" ></ProjectCard>
    </template>
  </DataTable>
  <a href="#" ref="commentButton" class="open-comments-sidebar hidden"
     data-turbolinks="false" data-object-type="Project" data-object-id=""></a>
  <ConfirmationModal
    :title="i18n.t('projects.index.modal_delete_folders.title')"
    :description="folderDeleteDescription"
    confirmClass="btn btn-danger"
    :confirmText="i18n.t('projects.index.modal_delete_folders.confirm_button')"
    ref="deleteFolderModal"
  ></ConfirmationModal>
  <ConfirmationModal
    :title="i18n.t('projects.export_projects.modal_title')"
    :description="exportDescription"
    confirmClass="btn btn-primary"
    :confirmText="i18n.t('projects.export_projects.export_button')"
    ref="exportModal"
  ></ConfirmationModal>
  <DescriptionModal
    v-if="descriptionModalObject"
    :object="descriptionModalObject"
    @update="updateDescription"
    @close="descriptionModalObject = null"/>
  <ExportLimitExceededModal v-if="exportLimitExceded" :description="exportDescription" @close="exportLimitExceded = false"/>
  <ProjectFormModal v-if="editProject"
                    :project="editProject" @close="editProject = null" @update="updateTable(); updateNavigator()" />
  <EditFolderModal v-if="editFolder" :folder="editFolder"
                   @close="editFolder = null" @update="updateTable(); updateNavigator()" />
  <ProjectFormModal v-if="newProject" :createUrl="createUrl"
                   :currentFolderId="currentFolderId"
                   @close="newProject = false" @create="updateTable(); updateNavigator()" />
  <NewFolderModal v-if="newFolder" :createFolderUrl="createFolderUrl"
                  :currentFolderId="currentFolderId" :viewMode="currentViewMode"
                  @close="newFolder = false" @create="updateTable(); updateNavigator()" />
  <MoveModal v-if="objectsToMove" :moveToUrl="moveToUrl"
             :selectedObjects="objectsToMove" :foldersTreeUrl="foldersTreeUrl"
             @close="objectsToMove = null" @move="updateTable(); updateNavigator(true)" />
  <AccessModal v-if="accessModalParams" :params="accessModalParams"
               @close="accessModalParams = null" @refresh="this.reloadingTable = true" />
</template>

<script>
/* global HelperModule */

import axios from '../../packs/custom_axios.js';

import DataTable from '../shared/datatable/table.vue';
import UsersRenderer from './renderers/users.vue';
import NameRenderer from './renderers/name.vue';
import StatusRenderer from './renderers/status.vue';
import CompletedTasksRenderer from './renderers/completed_tasks.vue';
import CompletedExperimentsRenderer from './renderers/completed_experiments.vue';
import SuperviserRenderer from './renderers/superviser.vue';
import CommentsRenderer from '../shared/datatable/renderers/comments.vue';
import DueDateRenderer from '../shared/datatable/renderers/date.vue';
import DescriptionRenderer from '../shared/datatable/renderers/description.vue';
import DescriptionModal from '../shared/datatable/modals/description.vue';
import ProjectCard from './card.vue';
import ConfirmationModal from '../shared/confirmation_modal.vue';
import ProjectFormModal from './modals/form.vue';
import EditFolderModal from './modals/edit_folder.vue';
import NewFolderModal from './modals/new_folder.vue';
import MoveModal from './modals/move.vue';
import AccessModal from '../shared/access_modal/modal.vue';
import ExportLimitExceededModal from './modals/export_limit_exceeded_modal.vue';
import FavoriteRenderer from '../shared/datatable/renderers/favorite.vue';

export default {
  name: 'ProjectsList',
  components: {
    DataTable,
    UsersRenderer,
    NameRenderer,
    ProjectCard,
    ConfirmationModal,
    ProjectFormModal,
    EditFolderModal,
    NewFolderModal,
    MoveModal,
    AccessModal,
    ExportLimitExceededModal,
    DueDateRenderer,
    DescriptionRenderer,
    DescriptionModal,
    StatusRenderer,
    SuperviserRenderer,
    FavoriteRenderer,
    CompletedTasksRenderer,
    CompletedExperimentsRenderer
  },
  props: {
    dataSource: { type: String, required: true },
    actionsUrl: { type: String, required: true },
    createUrl: { type: String },
    createFolderUrl: { type: String },
    activePageUrl: { type: String },
    archivedPageUrl: { type: String },
    currentViewMode: { type: String, required: true },
    usersFilterUrl: { type: String },
    headOfProjectUsersListUrl: { type: String },
    userRolesUrl: { type: String },
    currentFolderId: { type: String },
    foldersTreeUrl: { type: String },
    moveToUrl: { type: String }
  },
  data() {
    return {
      accessModalParams: null,
      newProject: false,
      newFolder: false,
      editProject: null,
      editFolder: null,
      objectsToMove: null,
      reloadingTable: false,
      exportLimitExceded: false,
      folderDeleteDescription: '',
      exportDescription: '',
      descriptionModalObject: null,
      statusesList: [
        ['not_started', this.i18n.t('projects.index.status.not_started')],
        ['in_progress', this.i18n.t('projects.index.status.in_progress')],
        ['done', this.i18n.t('projects.index.status.done')]
      ]
    };
  },
  computed: {
    columnDefs() {
      const columns = [{
        field: 'name',
        flex: 1,
        headerName: this.i18n.t('projects.index.card.name'),
        sortable: true,
        cellRenderer: 'NameRenderer'
      },
      {
        field: 'favorite',
        headerComponentParams: {
          html: '<div class="sn-icon sn-icon-star-filled"></div>'
        },
        headerName: this.i18n.t('projects.index.favorite'),
        sortable: true,
        cellRenderer: FavoriteRenderer,
        minWidth: 80,
        maxWidth: 80,
        notSelectable: true
      },
      {
        field: 'code',
        headerName: this.i18n.t('projects.index.card.id'),
        sortable: true
      },
      {
        field: 'status',
        headerName: this.i18n.t('projects.index.card.status'),
        sortable: true,
        cellRenderer: StatusRenderer,
        cellRendererParams: {
          statusesList: this.statusesList
        },
        notSelectable: true,
        minWidth: 180
      },
      {
        field: 'due_date',
        headerName: this.i18n.t('projects.index.due_date'),
        sortable: true,
        cellRenderer: DueDateRenderer,
        cellRendererParams: {
          placeholder: this.i18n.t('projects.index.add_due_date'),
          field: 'due_date_cell',
          mode: 'date',
          emptyPlaceholder: this.i18n.t('projects.index.no_due_date'),
          emitAction: 'updateDueDate'
        },
        minWidth: 200,
        notSelectable: true
      },
      {
        field: 'start_date',
        headerName: this.i18n.t('projects.index.start_date'),
        sortable: true,
        cellRenderer: DueDateRenderer,
        cellRendererParams: {
          placeholder: this.i18n.t('projects.index.add_start_date'),
          field: 'start_date_cell',
          mode: 'date',
          emptyPlaceholder: this.i18n.t('projects.index.no_start_date'),
          emitAction: 'updateStartDate'
        },
        minWidth: 200,
        notSelectable: true
      },
      {
        field: 'supervised_by',
        headerName: this.i18n.t('projects.index.card.supervised_by'),
        sortable: true,
        cellRenderer: SuperviserRenderer,
        notSelectable: true
      },
      {
        field: 'completed_experiments',
        headerName: this.i18n.t('projects.index.card.completed_experiment'),
        cellRenderer: CompletedExperimentsRenderer,
        sortable: true,
        minWidth: 110
      },
      {
        field: 'completed_tasks',
        headerName: this.i18n.t('experiments.table.column.completed_task'),
        cellRenderer: CompletedTasksRenderer,
        sortable: true,
        minWidth: 110
      },
      {
        field: 'created_at',
        headerName: this.i18n.t('projects.index.card.start_date'),
        sortable: true
      },
      {
        field: 'updated_at',
        headerName: this.i18n.t('projects.index.card.updated_at'),
        sortable: true
      },
      {
        field: 'users',
        headerName: this.i18n.t('projects.index.card.users'),
        cellRenderer: 'UsersRenderer',
        sortable: true,
        minWidth: 210,
        notSelectable: true
      },
      {
        field: 'comments',
        headerName: this.i18n.t('projects.index.card.comments'),
        sortable: true,
        cellRenderer: CommentsRenderer,
        notSelectable: true
      },
      {
        field: 'description',
        headerName: this.i18n.t('projects.index.card.description'),
        sortable: true,
        cellStyle: { 'white-space': 'normal' },
        cellRenderer: 'DescriptionRenderer',
        autoHeight: true,
        minWidth: 110
      }];
      if (this.currentViewMode === 'archived') {
        columns.push({
          field: 'archived_on',
          headerName: this.i18n.t('projects.index.card.archived_date'),
          sortable: true
        });
      }

      return columns;
    },
    toolbarActions() {
      const left = [];
      if (this.createUrl && this.currentViewMode !== 'archived') {
        left.push({
          name: 'create',
          icon: 'sn-icon sn-icon-new-task',
          label: this.i18n.t('projects.index.new'),
          type: 'emit',
          path: this.createUrl,
          buttonStyle: 'btn btn-primary'
        });
      }
      if (this.createFolderUrl) {
        left.push({
          name: 'create_folder',
          icon: 'sn-icon sn-icon-folder',
          label: this.i18n.t('projects.index.new_folder'),
          type: 'emit',
          path: this.createFolderUrl,
          buttonStyle: 'btn btn-light'
        });
      }
      return {
        left,
        right: []
      };
    },
    filters() {
      const filters = [
        {
          key: 'query',
          type: 'Text'
        },
        {
          key: 'start_date',
          type: 'DateRange',
          label: this.i18n.t('filters_modal.created_on.label'),
          mode: 'date'
        },
        {
          key: 'due_date',
          type: 'DateRange',
          label: this.i18n.t('filters_modal.due_date.label'),
          mode: 'date'
        }
      ];

      if (this.currentViewMode === 'archived') {
        filters.push({
          key: 'archived_on',
          type: 'DateRange',
          label: this.i18n.t('filters_modal.archived_on.label')
        });
      }

      filters.push({
        key: 'members',
        type: 'Select',
        optionsUrl: this.usersFilterUrl,
        optionRenderer: this.usersFilterRenderer,
        labelRenderer: this.usersFilterRenderer,
        label: this.i18n.t('projects.index.filters_modal.members.label'),
        placeholder: this.i18n.t('projects.index.filters_modal.members.placeholder')
      });

      filters.push({
        key: 'head_of_project',
        type: 'Select',
        optionsUrl: this.headOfProjectUsersListUrl,
        optionRenderer: this.usersFilterRenderer,
        labelRenderer: this.usersFilterRenderer,
        label: this.i18n.t('projects.index.filters_modal.head_of_project.label'),
        placeholder: this.i18n.t('projects.index.filters_modal.head_of_project.placeholder')
      });

      filters.push({
        key: 'statuses',
        type: 'Select',
        options: this.statusesList,
        label: this.i18n.t('projects.index.filters_modal.status.label'),
        placeholder: this.i18n.t('projects.index.filters_modal.status.placeholder')
      });

      filters.push({
        key: 'folder_search',
        type: 'Checkbox',
        label: this.i18n.t('projects.index.filters_modal.folders.label')
      });

      return filters;
    }
  },
  methods: {
    updateDueDate(value, params) {
      axios.put(params.data.urls.update, {
        project: {
          due_date: value
        }
      }).then(() => {
        this.updateTable();
      });
    },
    updateStartDate(value, params) {
      axios.put(params.data.urls.update, {
        project: {
          start_date: value
        }
      }).then(() => {
        this.updateTable();
      });
    },
    updateFavorite(value, params) {
      const url = value ? params.data.urls.favorite : params.data.urls.unfavorite;
      axios.post(url).then(() => {
        this.updateTable();
      });
    },
    showDescription(_e, project) {
      [this.descriptionModalObject] = project;
    },
    updateDescription(description) {
      axios.put(this.descriptionModalObject.urls.update, {
        project: {
          description
        }
      }).then(() => {
        this.updateTable();
      });
    },
    changeStatus(newStatus, params) {
      axios.put(params.data.urls.update, {
        project: {
          status: newStatus
        }
      }).then(() => {
        this.updateTable();
      });
    },
    changeSuperviser(newSuperviser, params) {
      axios.put(params.data.urls.update, {
        project: {
          supervised_by_id: newSuperviser[0]
        }
      }).then(() => {
        this.updateTable();
      });
    },
    formatDate(date) {
      if (!(date instanceof Date)) return null;

      const y = date.getFullYear();
      const m = date.getMonth() + 1;
      const d = date.getDate();
      return `${y}/${m}/${d}`;
    },
    usersFilterRenderer(option) {
      return `<div class="flex items-center gap-2">
                <img src="${option[2].avatar_url}" class="rounded-full w-6 h-6" />
                <span title="${option[1]}" class="truncate">${option[1]}</span>
              </div>`;
    },
    openComments(_params, rows) {
      $(this.$refs.commentButton).data('objectId', rows[0].id);
      this.$refs.commentButton.click();
    },
    access(event, rows) {
      this.accessModalParams = {
        object: rows[0],
        roles_path: this.userRolesUrl
      };
    },
    async archive(event, rows) {
      axios.post(event.path, { project_ids: rows.map((row) => row.id) }).then((response) => {
        this.reloadingTable = true;
        HelperModule.flashAlertMsg(response.data.message, 'success');
        this.updateNavigator(false);
      }).catch((error) => {
        HelperModule.flashAlertMsg(error.response.data.error, 'danger');
      });
    },
    restore(event, rows) {
      axios.post(event.path, { project_ids: rows.map((row) => row.id) }).then((response) => {
        this.reloadingTable = true;
        HelperModule.flashAlertMsg(response.data.message, 'success');
        this.updateNavigator(false);
      }).catch((error) => {
        HelperModule.flashAlertMsg(error.response.data.error, 'danger');
      });
    },
    edit(event, rows) {
      if (rows[0].folder) {
        [this.editFolder] = rows;
        return;
      }
      [this.editProject] = rows;
    },
    create() {
      this.newProject = true;
    },
    createFolder() {
      this.newFolder = true;
    },
    updateTable() {
      this.editProject = null;
      this.editFolder = null;
      this.newProject = false;
      this.newFolder = false;
      this.objectsToMove = null;
      this.reloadingTable = true;
      this.exportLimitExceded = false;
    },
    updateNavigator(withExpanedChildren = false) {
      window.navigatorContainer.reloadNavigator(withExpanedChildren);
    },
    async deleteFolder(event, rows) {
      const description = `
        <p>${this.i18n.t('projects.index.modal_delete_folders.description_1_html', { number: rows.length })}</p>
        <p>${this.i18n.t('projects.index.modal_delete_folders.description_2')}</p>`;
      this.folderDeleteDescription = description;
      const ok = await this.$refs.deleteFolderModal.show();
      if (ok) {
        axios.post(event.path, { project_folder_ids: rows.map((row) => row.id) }).then((response) => {
          this.reloadingTable = true;
          HelperModule.flashAlertMsg(response.data.message, 'success');
        }).catch((error) => {
          HelperModule.flashAlertMsg(error.response.data.error, 'danger');
        });
      }
    },
    async exportProjects(event, rows) {
      if (event.number_of_projects === 0) {
        HelperModule.flashAlertMsg(this.i18n.t('projects.export_projects.zero_projects_flash'), 'danger');
      } else if (event.number_of_request_left > 0) {
        this.exportDescription = event.message;
        const ok = await this.$refs.exportModal.show();
        if (ok) {
          axios.post(event.path, {
            project_ids: rows.filter((row) => !row.folder).map((row) => row.id),
            project_folder_ids: rows.filter((row) => row.folder).map((row) => row.id)
          }).then((response) => {
            this.reloadingTable = true;
            HelperModule.flashAlertMsg(response.data.flash, 'success');
          }).catch((error) => {
            HelperModule.flashAlertMsg(error.response.data.error, 'danger');
          });
        }
      } else {
        this.exportDescription = event.message;
        this.exportLimitExceded = true;
      }
    },
    move(event, rows) {
      this.objectsToMove = rows;
    }
  }
};

</script>
