<template>
  <div>
    <Notifications></Notifications>
    <div class="grid-view__public-shared-page">
      <Table
        :database="database"
        :table="table"
        :fields="fields"
        :view="view"
        :read-only="true"
        :table-loading="false"
        :store-prefix="'page/'"
      ></Table>
    </div>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'
import Notifications from '@baserow/modules/core/components/notifications/Notifications'
import Table from '@baserow/modules/database/components/table/Table'
import GridService from '@baserow/modules/database/services/view/grid'
import { DatabaseApplicationType } from '@baserow/modules/database/applicationTypes'
import { PUBLIC_PLACEHOLDER_ENTITY_ID } from '@baserow/modules/database/utils/constants'

export default {
  components: { Notifications, Table },
  /**
   * Fetches and prepares all the table, field and view data for the provided
   * public grid view.
   */
  async asyncData({ store, params, error, app, redirect, route }) {
    const slug = params.slug

    // in case the view is password protected, use the token saved in the cookies (if any)
    const publicAuthToken = await store.dispatch(
      'page/view/public/setAuthTokenFromCookies',
      { slug }
    )

    try {
      await store.dispatch('page/view/grid/setPublic', {
        isPublic: true,
        publicAuthToken,
      })

      const { data } = await GridService(app.$client).fetchPublicViewInfo(
        slug,
        publicAuthToken
      )

      const { applications } = await store.dispatch('application/forceSetAll', {
        applications: [
          {
            id: PUBLIC_PLACEHOLDER_ENTITY_ID,
            type: DatabaseApplicationType.getType(),
            tables: [{ id: PUBLIC_PLACEHOLDER_ENTITY_ID }],
          },
        ],
      })
      const database = applications[0]
      const table = database.tables[0]
      await store.dispatch('table/forceSelect', { database, table })

      await store.dispatch('field/forceSetFields', {
        fields: data.fields,
      })

      // We must manually set the filters disabled because it should always be false in
      // this case and it's not provided by the backend.
      data.view.filters_disabled = false
      data.view.filter_type = 'AND'
      const { view } = await store.dispatch('view/forceCreate', {
        data: data.view,
      })
      await store.dispatch('view/select', 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, data.fields, 'page/')
      return {
        database,
        table,
        view,
      }
    } catch (e) {
      const statusCode = e.response?.status
      // password protected view requires authentication
      if (statusCode === 401) {
        return redirect({
          name: 'database-public-view-auth',
          query: { original: route.path },
        })
      } else if (e.response?.status === 404) {
        return error({ statusCode: 404, message: 'View not found.' })
      } else {
        return error({ statusCode: 500, message: 'Error loading view.' })
      }
    }
  },
  head() {
    return {
      title: this.view.name || '',
    }
  },
  computed: {
    ...mapGetters({
      fields: 'field/getAll',
    }),
  },
  mounted() {
    if (!this.$env.DISABLE_ANONYMOUS_PUBLIC_VIEW_WS_CONNECTIONS) {
      this.$realtime.connect(true, true)

      const token = this.$store.getters['page/view/public/getAuthToken']
      this.$realtime.subscribe('view', { slug: this.$route.params.slug, token })
    }
  },
  beforeDestroy() {
    if (!this.$env.DISABLE_ANONYMOUS_PUBLIC_VIEW_WS_CONNECTIONS) {
      this.$realtime.subscribe(null)
      this.$realtime.disconnect()
    }
  },
}
</script>