import { defineComponent } from 'vue'
import { mapActions } from 'vuex'
import debounce from 'lodash.debounce'
import FtCard from '../../components/ft-card/ft-card.vue'
import FtFlexBox from '../../components/ft-flex-box/ft-flex-box.vue'
import FtTooltip from '../../components/ft-tooltip/ft-tooltip.vue'
import FtLoader from '../../components/ft-loader/ft-loader.vue'
import FtButton from '../../components/ft-button/ft-button.vue'
import FtSelect from '../../components/ft-select/ft-select.vue'
import FtElementList from '../../components/ft-element-list/ft-element-list.vue'
import FtInput from '../../components/ft-input/ft-input.vue'
import FtIconButton from '../../components/ft-icon-button/ft-icon-button.vue'

const SORT_BY_VALUES = {
  NameAscending: 'name_ascending',
  NameDescending: 'name_descending',

  LatestCreatedFirst: 'latest_created_first',
  EarliestCreatedFirst: 'earliest_created_first',

  LatestUpdatedFirst: 'latest_updated_first',
  EarliestUpdatedFirst: 'earliest_updated_first',

  LatestPlayedFirst: 'latest_played_first',
  EarliestPlayedFirst: 'earliest_played_first',
}

export default defineComponent({
  name: 'UserPlaylists',
  components: {
    'ft-card': FtCard,
    'ft-flex-box': FtFlexBox,
    'ft-tooltip': FtTooltip,
    'ft-loader': FtLoader,
    'ft-button': FtButton,
    'ft-select': FtSelect,
    'ft-element-list': FtElementList,
    'ft-icon-button': FtIconButton,
    'ft-input': FtInput,
  },
  data: function () {
    return {
      isLoading: false,
      dataLimit: 100,
      searchDataLimit: 100,
      showLoadMoreButton: false,
      query: '',
      activeData: [],
      sortBy: SORT_BY_VALUES.LatestPlayedFirst,
    }
  },
  computed: {
    locale: function () {
      return this.$i18n.locale.replace('_', '-')
    },

    allPlaylists: function () {
      const playlists = this.$store.getters.getAllPlaylists
      return [].concat(playlists).sort((a, b) => {
        switch (this.sortBy) {
          case SORT_BY_VALUES.NameAscending:
            return a.playlistName.localeCompare(b.playlistName, this.locale)
          case SORT_BY_VALUES.NameDescending:
            return b.playlistName.localeCompare(a.playlistName, this.locale)
          case SORT_BY_VALUES.LatestCreatedFirst: {
            if (a.createdAt > b.createdAt) { return -1 }
            if (a.createdAt < b.createdAt) { return 1 }

            return a.playlistName.localeCompare(b.playlistName, this.locale)
          }
          case SORT_BY_VALUES.EarliestCreatedFirst: {
            if (a.createdAt < b.createdAt) { return -1 }
            if (a.createdAt > b.createdAt) { return 1 }

            return a.playlistName.localeCompare(b.playlistName, this.locale)
          }
          case SORT_BY_VALUES.LatestUpdatedFirst: {
            if (a.lastUpdatedAt > b.lastUpdatedAt) { return -1 }
            if (a.lastUpdatedAt < b.lastUpdatedAt) { return 1 }

            return a.playlistName.localeCompare(b.playlistName, this.locale)
          }
          case SORT_BY_VALUES.EarliestUpdatedFirst: {
            if (a.lastUpdatedAt < b.lastUpdatedAt) { return -1 }
            if (a.lastUpdatedAt > b.lastUpdatedAt) { return 1 }

            return a.playlistName.localeCompare(b.playlistName, this.locale)
          }
          case SORT_BY_VALUES.LatestPlayedFirst: {
            if (a.lastPlayedAt == null && b.lastPlayedAt == null) {
              return a.playlistName.localeCompare(b.playlistName, this.locale)
            }
            // Never played playlist = move to last
            if (a.lastPlayedAt == null) { return 1 }
            if (b.lastPlayedAt == null) { return -1 }
            if (a.lastPlayedAt > b.lastPlayedAt) { return -1 }
            if (a.lastPlayedAt < b.lastPlayedAt) { return 1 }

            return a.playlistName.localeCompare(b.playlistName, this.locale)
          }
          case SORT_BY_VALUES.EarliestPlayedFirst: {
            // Never played playlist = first
            if (a.lastPlayedAt == null && b.lastPlayedAt == null) {
              return a.playlistName.localeCompare(b.playlistName, this.locale)
            }
            // Never played playlist = move to first
            if (a.lastPlayedAt == null) { return -1 }
            if (b.lastPlayedAt == null) { return 1 }
            if (a.lastPlayedAt < b.lastPlayedAt) { return -1 }
            if (a.lastPlayedAt > b.lastPlayedAt) { return 1 }

            return a.playlistName.localeCompare(b.playlistName, this.locale)
          }
          default:
            console.error(`Unknown sortBy: ${this.sortBy}`)
            return 0
        }
      })
    },

    fullData: function () {
      const data = this.allPlaylists
      if (this.allPlaylists.length < this.dataLimit) {
        return data
      } else {
        return data.slice(0, this.dataLimit)
      }
    },

    lowerCaseQuery: function() {
      return this.query.toLowerCase()
    },

    sortBySelectNames() {
      return Object.values(SORT_BY_VALUES).map((k) => {
        switch (k) {
          case SORT_BY_VALUES.NameAscending:
            return this.$t('User Playlists.Sort By.NameAscending')
          case SORT_BY_VALUES.NameDescending:
            return this.$t('User Playlists.Sort By.NameDescending')
          case SORT_BY_VALUES.LatestCreatedFirst:
            return this.$t('User Playlists.Sort By.LatestCreatedFirst')
          case SORT_BY_VALUES.EarliestCreatedFirst:
            return this.$t('User Playlists.Sort By.EarliestCreatedFirst')
          case SORT_BY_VALUES.LatestUpdatedFirst:
            return this.$t('User Playlists.Sort By.LatestUpdatedFirst')
          case SORT_BY_VALUES.EarliestUpdatedFirst:
            return this.$t('User Playlists.Sort By.EarliestUpdatedFirst')
          case SORT_BY_VALUES.LatestPlayedFirst:
            return this.$t('User Playlists.Sort By.LatestPlayedFirst')
          case SORT_BY_VALUES.EarliestPlayedFirst:
            return this.$t('User Playlists.Sort By.EarliestPlayedFirst')
          default:
            console.error(`Unknown sortBy: ${k}`)
            return k
        }
      })
    },
    sortBySelectValues() {
      return Object.values(SORT_BY_VALUES)
    },
  },
  watch: {
    lowerCaseQuery() {
      this.searchDataLimit = 100
      this.filterPlaylistAsync()
    },
    fullData() {
      this.activeData = this.fullData
      this.filterPlaylist()
    },
    sortBy() {
      sessionStorage.setItem('UserPlaylists/sortBy', this.sortBy)
    },
  },
  mounted: function () {
    const limit = sessionStorage.getItem('favoritesLimit')
    if (limit !== null) {
      this.dataLimit = limit
    }

    const sortBy = sessionStorage.getItem('UserPlaylists/sortBy')
    if (sortBy != null) {
      this.sortBy = sortBy
    }

    this.activeData = this.fullData

    this.showLoadMoreButton = this.activeData.length < this.allPlaylists.length

    this.filterPlaylistDebounce = debounce(this.filterPlaylist, 500)
  },
  methods: {
    increaseLimit: function () {
      if (this.query !== '') {
        this.searchDataLimit += 100
        this.filterPlaylist()
      } else {
        this.dataLimit += 100
        sessionStorage.setItem('favoritesLimit', this.dataLimit)
      }
    },
    filterPlaylistAsync: function() {
      // Updating list on every char input could be wasting resources on rendering
      // So run it with delay (to be cancelled when more input received within time)
      this.filterPlaylistDebounce()
    },
    filterPlaylist: function() {
      if (this.lowerCaseQuery === '') {
        this.activeData = this.fullData
        this.showLoadMoreButton = this.allPlaylists.length > this.activeData.length
      } else {
        const filteredPlaylists = this.allPlaylists.filter((playlist) => {
          if (typeof (playlist.playlistName) !== 'string') { return false }

          return playlist.playlistName.toLowerCase().includes(this.lowerCaseQuery)
        })
        this.showLoadMoreButton = filteredPlaylists.length > this.searchDataLimit
        this.activeData = filteredPlaylists.length < this.searchDataLimit ? filteredPlaylists : filteredPlaylists.slice(0, this.searchDataLimit)
      }
    },

    createNewPlaylist: function () {
      this.showCreatePlaylistPrompt({
        title: '',
      })
    },

    ...mapActions([
      'showCreatePlaylistPrompt'
    ])
  }
})
