<template>
  <main class="container is-fluid">
    <h1 class="title">Repositories</h1>
    <h2 class="subtitle">Manage Git repositories</h2>
    <Paginator
      :response="reposPage"
      v-slot="{ results }"
      :loading="loading"
    >
      <table class="table is-fullwidth is-hoverable">
        <thead>
          <tr>
            <th>URL</th>
            <th>Workers</th>
            <th v-if="hasFeature('enterprise')">Users</th>
            <th v-if="isVerified">Actions</th>
          </tr>
        </thead>
        <tbody>
          <Row
            v-for="repo in results"
            :key="repo.id"
            :repo="repo"
            v-on:remove="repoDeletion = repo"
          />
        </tbody>
      </table>
    </Paginator>
    <DeleteModal
      v-if="repoDeletion"
      v-model:modal="deleteModal"
      :repo="repoDeletion"
      v-on:delete="handleDeletion"
    />
  </main>
</template>

<script lang="ts">
import { defineComponent } from 'vue'
import { useRepositoryStore, useNotificationStore } from '@/stores'
import { mapActions, mapState } from 'pinia'
import { mapGetters } from 'vuex'
import { errorParser } from '@/helpers'
import Paginator from '@/components/Paginator.vue'
import Row from '@/components/Repos/Row.vue'
import DeleteModal from '@/components/Repos/DeleteModal.vue'
import { PageNumberPagination } from '@/types'
import { Repository } from '@/types/worker'

const Component = defineComponent({
  components: {
    Paginator,
    Row,
    DeleteModal
  },
  data: () => ({
    loading: false,
    // Stores a repository to delete. Automatically prompt the deletion modal
    repoDeletion: null as Repository | null,
    deleteModal: false,
    reposPage: null as PageNumberPagination<Repository> | null
  }),
  beforeRouteEnter ({ query }, from, next) {
    /*
     * In order to not get typing error related to 'vm', we name the component which allos us to tell TypeScript that vm
     * is of the same type as that component.
     */
    next(vm => (vm as InstanceType<typeof Component>).updatePage(parseInt(`${query.page ?? 1}`)))
  },
  beforeRouteUpdate ({ query }) {
    this.updatePage(parseInt(`${query.page ?? 1}`))
  },
  computed: {
    ...mapGetters('auth', ['isVerified', 'hasFeature']),
    ...mapState(useRepositoryStore, ['repositories'])
  },
  methods: {
    ...mapActions(useNotificationStore, ['notify']),
    ...mapActions(useRepositoryStore, ['listRepository']),
    async updatePage (page: number) {
      this.loading = true
      try {
        this.reposPage = await this.listRepository(page)
      } catch (err) {
        this.notify({ type: 'error', text: `An error occurred listing repositories: ${errorParser(err)}` })
      } finally {
        this.loading = false
      }
    },
    handleDeletion () {
      // Reload repositories page
      this.repoDeletion = null
      this.updatePage(parseInt(`${this.$route.query.page ?? 1}`))
    }
  },
  watch: {
    repoDeletion (repo) {
      if (repo) this.deleteModal = true
    },
    deleteModal (open) {
      if (!open) this.repoDeletion = null
    }
  }
})

export default Component
</script>