<template>
  <div @scroll="onScroll" class="full-height fit scroll q-pa-sm">
    <template v-if="isShow && isConnected">
      <ui-notifications-header
        v-if="isInitialized"
        :is-empty="isEmpty"
        :is-loading="isLoading"
      />
      <ui-notifications-config v-if="isShowConfig" />
      <ui-notification-clear-all-btn
        v-if="notifications.length && isShowClearAllNotifications"
      />
      <ui-notifications-scroll
        v-if="notifications.length"
        v-show="!isShowConfig"
      >
        <div class="flex column">
          <ui-notification-list :notifications="notifications" />
        </div>
      </ui-notifications-scroll>
      <ui-notification-state
        v-if="isEmpty && !isShowConfig"
        icon="las la-coffee"
        text="Кофе тайм"
      />
      <ui-page-loading :showing="isLoading" />
    </template>

    <ui-notification-state
      v-if="!isInitialized || !isConnected"
      icon="las la-hourglass-half"
      text="Немного подождите...."
    />

    <ui-popup-notifications v-if="notifications.length" />
  </div>
</template>

<script lang="ts">
import { Component, Prop, Vue, Watch } from 'vue-property-decorator'
import UiNotificationsHeader from './notifications/header/UiNotificationsHeader.vue'
import UiNotificationList from './notifications/UiNotificationList.vue'
import NotificationWebsocketService from './notifications/services/NotificationWebsocketService'
import Config from './notifications/types/Config'
import NotificationsStore, {
  getNotificationsStore,
} from './notifications/stores/NotificationsStore'
import NotificationService from './notifications/services/NotificationService'
import UiNotificationsConfig from './notifications/config/UiNotificationsConfig.vue'
import LocalStorageHelper from './notifications/helpers/LocalStorageHelper'
import UiPageLoading from '../UiPageLoading.vue'
import NotificationsConfigStore, {
  getNotificationsConfigStore,
} from './notifications/stores/NotificationsConfigStore'
import { playNotificationSound } from './notifications/helpers/NotificationAudio'
import UiPopupNotifications from './notifications/UiPopupNotifications.vue'
import UiNotificationState from './notifications/UiNotificationState.vue'
import UiNotificationsScroll from './notifications/UiNotificationsScroll.vue'
import UiNotificationClearAllBtn from './notifications/UiNotificationClearAllBtn.vue'
import { AuthService } from '@/services/AuthService'

@Component({
  components: {
    UiNotificationClearAllBtn,
    UiNotificationsScroll,
    UiNotificationState,
    UiPopupNotifications,
    UiPageLoading,
    UiNotificationsConfig,
    UiNotificationList,
    UiNotificationsHeader,
  },
  inheritAttrs: false,
})
export default class UiNotifications extends Vue {
  @Prop(String) clientUid!: string
  @Prop(String) projectId!: string
  @Prop(String) backendHost!: string
  @Prop(String) wsHost!: string
  @Prop(String) authTokenUrl!: string
  @Prop(Boolean) isShow!: boolean

  notificationStore!: NotificationsStore
  notificationConfigStore!: NotificationsConfigStore
  isInitialized = false
  isConnected = false
  isShowClearAllNotifications = false

  async created() {
    this.notificationConfigStore = getNotificationsConfigStore(this.$store)
    this.notificationStore = getNotificationsStore(this.$store)

    const token = await AuthService.getAuthToken(this.backendHost)

    await this.beforeInit()
    await this.initWebsocket(token)

    this.isInitialized = true
  }

  get notifications() {
    return this.notificationStore.filteredNotifications
  }

  get isShowConfig() {
    return this.notificationConfigStore.isShowConfig
  }

  get isLoading() {
    return (
      this.notificationStore.isLoading && this.isInitialized && this.isConnected
    )
  }

  get isEmpty(): boolean {
    return this.isInitialized && !this.notifications.length && !this.isLoading
  }

  beforeInit() {
    NotificationService.init({
      backendHost: this.backendHost,
      projectId: this.projectId,
    })

    LocalStorageHelper.init({ clientUid: this.clientUid })
  }

  async loadInitialData() {
    await this.notificationStore.loadTypesCount()

    await this.notificationStore.setClientUid(this.clientUid)

    await this.notificationConfigStore.setNotificationCount(
      LocalStorageHelper.getNotificationsCount() || 5
    )

    await this.notificationConfigStore.setNotificationDuration(
      LocalStorageHelper.getDuration() || 20
    )

    await this.notificationStore.setExcludedTypes(
      LocalStorageHelper.getExcludedTypes()
    )

    await this.notificationStore.setExcludedPopupTypes(
      LocalStorageHelper.getExcludedPopupTypes()
    )

    await this.notificationStore.loadNotifications()
  }

  async initWebsocket(token: string) {
    const config: Config = {
      wsHost: this.wsHost,
      backendHost: this.backendHost,
    }

    try {
      NotificationWebsocketService.init({
        config,
        authToken: token,
        clientUid: this.clientUid,
        projectId: this.projectId,
      })
        .onNewNotification(({ notification }) => {
          this.notificationStore.addNotification(notification)

          if (!this.notificationConfigStore.isMuted) {
            playNotificationSound()
          }
        })
        .onCloseNotification(({ notification }) => {
          this.notificationStore.deleteNotification(notification.id)
          this.notificationStore.removePopupNotification(notification.id)
        })
        .onCloseAllNotifications(() => {
          this.notificationStore.clearNotifications()
        })
        .onDisconnect(() => {
          this.isConnected = false
        })
        .onConnect(() => {
          this.isConnected = true
        })
    } catch (error) {
      console.log(
        'Notification service: error in AuthService.getAuthToken().',
        error.message
      )
    }
  }

  onScroll(event: Event & { target: HTMLElement }) {
    this.isShowClearAllNotifications = event.target.scrollTop > 500
  }

  @Watch('isConnected')
  async loadInitialDataOnConnect(isConnected: boolean) {
    if (isConnected) {
      await this.notificationStore.setIsLoading(true)
      await this.loadInitialData()
    } else {
      this.notificationStore.clearNotifications()
    }
  }
}
</script>
