<template>
  <div>
    <header class="layout-col-3-1 header">
      <ul class="header-filter">
        <li class="header-filter-item">
          <a
            ref="viewsSelectToggle"
            class="header-filter-link"
            @click="$refs.viewsContext.toggle($refs.viewsSelectToggle)"
          >
            <span v-if="hasSelectedView">
              <i
                class="header-filter-icon fas"
                :class="'fa-' + selectedView._.type.iconClass"
              ></i>
              {{ selectedView.name }}
            </span>
            <span v-if="!hasSelectedView">
              <i
                class="header-filter-icon header-filter-icon-no-choice fas fa-caret-square-down"
              ></i>
              Choose view
            </span>
          </a>
          <ViewsContext ref="viewsContext" :table="table"></ViewsContext>
        </li>
      </ul>
      <template v-if="hasSelectedView">
        <component
          :is="getViewHeaderComponent(selectedView)"
          :database="database"
          :table="table"
          :view="selectedView"
          :fields="fields"
          :primary="primary"
        />
      </template>
      <ul class="header-info">
        <li>{{ database.name }}</li>
        <li>{{ table.name }}</li>
      </ul>
    </header>
    <div class="layout-col-3-2 content">
      <template v-if="hasSelectedView">
        <component
          :is="getViewComponent(selectedView)"
          :database="database"
          :table="table"
          :view="selectedView"
          :fields="fields"
          :primary="primary"
        />
      </template>
    </div>
  </div>
</template>

<script>
import { mapState, mapGetters } from 'vuex'

import ViewsContext from '@baserow/modules/database/components/view/ViewsContext'

/**
 * This page component is the skeleton for a table. Depending on the selected view it
 * will load the correct components into the header and body.
 */
export default {
  layout: 'app',
  components: {
    ViewsContext,
  },
  /**
   * Prepares all the table, field and view data for the provided database, table and
   * view id.
   */
  async asyncData({ store, params, error, app }) {
    // @TODO figure out why the id's aren't converted to an int in the route.
    const databaseId = parseInt(params.databaseId)
    const tableId = parseInt(params.tableId)
    const viewId = params.viewId ? parseInt(params.viewId) : null
    const data = {}

    // Try to find the table in the already fetched applications by the
    // groupsAndApplications middleware and select that one. By selecting the table, the
    // fields and views are also going to be fetched.
    try {
      const { database, table } = await store.dispatch('table/selectById', {
        databaseId,
        tableId,
      })
      await store.dispatch('group/selectById', database.group.id)
      data.database = database
      data.table = table
    } catch (e) {
      return error({ statusCode: 404, message: 'Table not found.' })
    }

    // If a view id is provided and the table is selected we can select the view. The
    // views that belong to the table have already been fetched so we just need to
    // select the correct one.
    if (viewId !== null) {
      try {
        const { view } = await store.dispatch('view/selectById', viewId)
        data.view = view

        // It might be possible that the view also has some stores that need to be
        // filled with initial data so we're going to call the fetch function here.
        const type = app.$registry.get('view', view.type)
        await type.fetch({ store }, view)
      } catch {
        return error({ statusCode: 404, message: 'View not found.' })
      }
    }

    return data
  },
  computed: {
    ...mapState({
      selectedView: (state) => state.view.selected,
      fields: (state) => state.field.items,
      primary: (state) => state.field.primary,
    }),
    ...mapGetters({
      hasSelectedView: 'view/hasSelected',
    }),
  },
  beforeRouteLeave(to, from, next) {
    this.$store.dispatch('table/unselect')
    next()
  },
  methods: {
    getViewComponent(view) {
      const type = this.$registry.get('view', view.type)
      return type.getComponent()
    },
    getViewHeaderComponent(view) {
      const type = this.$registry.get('view', view.type)
      return type.getHeaderComponent()
    },
  },
  head() {
    return {
      title: (this.view ? this.view.name + ' - ' : '') + this.table.name,
    }
  },
}
</script>