<template>
  <div ref="page" id="page-wrapper" class="page px-6 pt-6 pb-52 overflow-y-auto" :class="streamAudiobook ? 'streaming' : ''">
    <div class="border border-white border-opacity-10 max-w-7xl mx-auto mb-10 mt-5">
      <div class="flex items-center px-4 py-4 cursor-pointer" @click="openMapOptions = !openMapOptions" @mousedown.prevent @mouseup.prevent>
        <span class="material-icons">{{ openMapOptions ? 'expand_less' : 'expand_more' }}</span>

        <p class="ml-4 text-gray-200 text-lg">Map details</p>
      </div>
      <div class="overflow-hidden">
        <transition name="slide">
          <div v-if="openMapOptions" class="flex flex-wrap">
            <div class="flex items-center px-4 w-1/2">
              <ui-checkbox v-model="selectedBatchUsage.subtitle" />
              <ui-text-input-with-label ref="subtitleInput" v-model="batchDetails.subtitle" :disabled="!selectedBatchUsage.subtitle" label="Subtitle" class="mb-4 ml-4" />
            </div>
            <div class="flex items-center px-4 w-1/2">
              <ui-checkbox v-model="selectedBatchUsage.author" />
              <ui-text-input-with-label ref="authorInput" v-model="batchDetails.author" :disabled="!selectedBatchUsage.author" label="Author" class="mb-4 ml-4" />
            </div>
            <div class="flex items-center px-4 w-1/2">
              <ui-checkbox v-model="selectedBatchUsage.publishYear" />
              <ui-text-input-with-label ref="publishYearInput" v-model="batchDetails.publishYear" :disabled="!selectedBatchUsage.publishYear" label="Publish Year" class="mb-4 ml-4" />
            </div>
            <div class="flex items-center px-4 w-1/2">
              <ui-checkbox v-model="selectedBatchUsage.series" />
              <ui-input-dropdown ref="seriesDropdown" v-model="batchDetails.series" :disabled="!selectedBatchUsage.series" label="Series" :items="seriesItems" @input="seriesChanged" @newItem="newSeriesItem" class="mb-4 ml-4" />
            </div>
            <div class="flex items-center px-4 w-1/2">
              <ui-checkbox v-model="selectedBatchUsage.genres" />
              <ui-multi-select ref="genresSelect" v-model="batchDetails.genres" :disabled="!selectedBatchUsage.genres" label="Genres" :items="genreItems" @newItem="newGenreItem" @removedItem="removedGenreItem" class="mb-4 ml-4" />
            </div>
            <div class="flex items-center px-4 w-1/2">
              <ui-checkbox v-model="selectedBatchUsage.tags" />
              <ui-multi-select ref="tagsSelect" v-model="batchDetails.tags" label="Tags" :disabled="!selectedBatchUsage.tags" :items="tagItems" @newItem="newTagItem" @removedItem="removedTagItem" class="mb-4 ml-4" />
            </div>
            <div class="flex items-center px-4 w-1/2">
              <ui-checkbox v-model="selectedBatchUsage.narrator" />
              <ui-text-input-with-label ref="narratorInput" v-model="batchDetails.narrator" :disabled="!selectedBatchUsage.narrator" label="Narrator" class="mb-4 ml-4" />
            </div>
            <div class="flex items-center px-4 w-1/2">
              <ui-checkbox v-model="selectedBatchUsage.publisher" />
              <ui-text-input-with-label ref="publisherInput" v-model="batchDetails.publisher" :disabled="!selectedBatchUsage.publisher" label="Publisher" class="mb-4 ml-4" />
            </div>
            <div class="flex items-center px-4 w-1/2">
              <ui-checkbox v-model="selectedBatchUsage.language" />
              <ui-text-input-with-label ref="languageInput" v-model="batchDetails.language" :disabled="!selectedBatchUsage.language" label="Language" class="mb-4 ml-4" />
            </div>

            <div class="w-full flex items-center justify-end p-4">
              <ui-btn color="success" :disabled="!hasSelectedBatchUsage" :padding-x="8" small class="text-base" :loading="isProcessing" @click="mapBatchDetails">Apply</ui-btn>
            </div>
          </div>
        </transition>
      </div>
    </div>

    <div class="flex justify-center flex-wrap">
      <template v-for="audiobook in audiobookCopies">
        <div :key="audiobook.id" class="w-full max-w-3xl border border-black-300 p-6 -ml-px -mt-px flex">
          <div class="w-32">
            <covers-book-cover :audiobook="audiobook.originalAudiobook" :width="120" :book-cover-aspect-ratio="bookCoverAspectRatio" />
          </div>
          <div class="flex-grow pl-4">
            <ui-text-input-with-label v-model="audiobook.book.title" label="Title" />

            <ui-text-input-with-label v-model="audiobook.book.subtitle" label="Subtitle" class="mt-2" />

            <div class="flex mt-2 -mx-1">
              <div class="w-3/4 px-1">
                <ui-text-input-with-label v-model="audiobook.book.author" label="Author" />
              </div>
              <div class="flex-grow px-1">
                <ui-text-input-with-label v-model="audiobook.book.publishYear" type="number" label="Publish Year" />
              </div>
            </div>

            <div class="flex mt-2 -mx-1">
              <div class="w-3/4 px-1">
                <ui-input-dropdown v-model="audiobook.book.series" label="Series" :items="seriesItems" @input="seriesChanged" @newItem="newSeriesItem" />
              </div>
              <div class="flex-grow px-1">
                <ui-text-input-with-label v-model="audiobook.book.volumeNumber" label="Volume #" />
              </div>
            </div>

            <ui-textarea-with-label v-model="audiobook.book.description" :rows="3" label="Description" class="mt-2" />

            <div class="flex mt-2 -mx-1">
              <div class="w-1/2 px-1">
                <ui-multi-select v-model="audiobook.book.genres" label="Genres" :items="genreItems" @newItem="newGenreItem" @removedItem="removedGenreItem" />
              </div>
              <div class="flex-grow px-1">
                <ui-multi-select v-model="audiobook.tags" label="Tags" :items="tagItems" @newItem="newTagItem" @removedItem="removedTagItem" />
              </div>
            </div>

            <!-- <div class="flex mt-2 -mx-1">
              <div class="w-1/2 px-1">
                <ui-text-input-with-label v-model="audiobook.book.narrator" label="Narrator" />
              </div>
            </div> -->
            <div class="flex mt-2 -mx-1">
              <div class="w-1/3 px-1">
                <ui-text-input-with-label v-model="audiobook.book.narrator" label="Narrator" />
              </div>
              <div class="w-1/3 px-1">
                <ui-text-input-with-label v-model="audiobook.book.publisher" label="Publisher" />
              </div>
              <div class="flex-grow px-1">
                <ui-text-input-with-label v-model="audiobook.book.language" label="Language" />
              </div>
            </div>

            <div class="flex mt-2 -mx-1">
              <div class="w-1/3 px-1">
                <ui-text-input-with-label v-model="audiobook.book.isbn" label="ISBN" />
              </div>
              <div class="w-1/3 px-1">
                <ui-text-input-with-label v-model="audiobook.book.asin" label="ASIN" />
              </div>
            </div>
          </div>
        </div>
      </template>
    </div>
    <div v-show="isProcessing" class="fixed top-0 left-0 z-50 w-full h-full flex items-center justify-center bg-black bg-opacity-60">
      <ui-loading-indicator />
    </div>

    <div :class="isScrollable ? 'fixed left-0 box-shadow-lg-up bg-primary' : ''" class="w-full h-20 px-4 flex items-center border-t border-bg z-40" :style="{ bottom: streamAudiobook ? '165px' : '0px' }">
      <div class="flex-grow" />
      <ui-btn color="success" :padding-x="8" class="text-lg" :loading="isProcessing" @click.prevent="saveClick">Save</ui-btn>
    </div>
  </div>
</template>

<script>
export default {
  async asyncData({ store, redirect, app }) {
    if (!store.state.selectedAudiobooks.length) {
      return redirect('/')
    }
    var audiobooks = await app.$axios.$post(`/api/books/batch/get`, { books: store.state.selectedAudiobooks }).catch((error) => {
      var errorMsg = error.response.data || 'Failed to get audiobooks'
      console.error(errorMsg, error)
      return []
    })
    return {
      audiobooks
    }
  },
  data() {
    return {
      isProcessing: false,
      audiobookCopies: [],
      isScrollable: false,
      newSeriesItems: [],
      newTagItems: [],
      newGenreItems: [],
      batchDetails: {
        subtitle: null,
        author: null,
        publishYear: null,
        series: null,
        genres: [],
        tags: [],
        narrator: null,
        publisher: null,
        language: null
      },
      selectedBatchUsage: {
        subtitle: false,
        author: false,
        publishYear: false,
        series: false,
        genres: false,
        tags: false,
        narrator: false,
        publisher: false,
        language: false
      },
      openMapOptions: false
    }
  },
  computed: {
    coverAspectRatio() {
      return this.$store.getters['getServerSetting']('coverAspectRatio')
    },
    bookCoverAspectRatio() {
      return this.coverAspectRatio === this.$constants.BookCoverAspectRatio.SQUARE ? 1 : 1.6
    },
    streamAudiobook() {
      return this.$store.state.streamAudiobook
    },
    genreItems() {
      return this.genres.concat(this.newGenreItems)
    },
    tagItems() {
      return this.tags.concat(this.newTagItems)
    },
    seriesItems() {
      return [...this.series, ...this.newSeriesItems]
    },
    genres() {
      return this.filterData.genres || []
    },
    tags() {
      return this.filterData.tags || []
    },
    series() {
      return this.filterData.series || []
    },
    filterData() {
      return this.$store.state.libraries.filterData || {}
    },
    currentLibraryId() {
      return this.$store.state.libraries.currentLibraryId
    },
    hasSelectedBatchUsage() {
      return Object.values(this.selectedBatchUsage).some((b) => !!b)
    }
  },
  methods: {
    blurBatchForm() {
      if (this.$refs.seriesDropdown && this.$refs.seriesDropdown.isFocused) {
        this.$refs.seriesDropdown.blur()
      }
      if (this.$refs.genresSelect && this.$refs.genresSelect.isFocused) {
        this.$refs.genresSelect.forceBlur()
      }
      if (this.$refs.tagsSelect && this.$refs.tagsSelect.isFocused) {
        this.$refs.tagsSelect.forceBlur()
      }

      for (const key in this.batchDetails) {
        if (this.$refs[`${key}Input`] && this.$refs[`${key}Input`].blur) {
          this.$refs[`${key}Input`].blur()
        }
      }
    },
    mapBatchDetails() {
      this.blurBatchForm()

      this.audiobookCopies = this.audiobookCopies.map((ab) => {
        for (const key in this.selectedBatchUsage) {
          if (this.selectedBatchUsage[key]) {
            if (key === 'tags') {
              ab.tags = this.batchDetails.tags
            } else {
              ab.book[key] = this.batchDetails[key]
            }
          }
        }
        return ab
      })
      this.$toast.success('Details mapped')
    },
    newTagItem(item) {
      if (item && !this.newTagItems.includes(item)) {
        this.newTagItems.push(item)
      }
    },
    removedTagItem(item) {
      // If newly added, remove if not used on any other audiobooks
      if (item && this.newTagItems.includes(item)) {
        var usedByOtherAb = this.audiobookCopies.find((ab) => {
          return ab.tags && ab.tags.includes(item)
        })
        if (!usedByOtherAb) {
          this.newTagItems = this.newTagItems.filter((t) => t !== item)
        }
      }
    },
    newGenreItem(item) {
      if (item && !this.newGenreItems.includes(item)) {
        this.newGenreItems.push(item)
      }
    },
    removedGenreItem(item) {
      // If newly added, remove if not used on any other audiobooks
      if (item && this.newGenreItems.includes(item)) {
        var usedByOtherAb = this.audiobookCopies.find((ab) => {
          return ab.book.genres && ab.book.genres.includes(item)
        })
        if (!usedByOtherAb) {
          this.newGenreItems = this.newGenreItems.filter((t) => t !== item)
        }
      }
    },
    newSeriesItem(item) {
      if (item && !this.newSeriesItems.includes(item)) {
        this.newSeriesItems.push(item)
      }
    },
    seriesChanged() {
      this.newSeriesItems = this.newSeriesItems.filter((item) => {
        return this.audiobookCopies.find((ab) => ab.book.series === item)
      })
    },
    init() {
      this.audiobookCopies = this.audiobooks.map((ab) => {
        var copy = { ...ab }
        copy.tags = [...ab.tags]
        copy.book = { ...ab.book }
        copy.book.genres = [...ab.book.genres]
        copy.originalAudiobook = ab
        return copy
      })
      this.$nextTick(() => {
        if (this.$refs.page.scrollHeight > this.$refs.page.clientHeight) {
          this.isScrollable = true
        }
      })
    },
    compareStringArrays(arr1, arr2) {
      if (!arr1 || !arr2) return false
      return arr1.join(',') !== arr2.join(',')
    },
    compareAudiobooks(newAb, origAb) {
      const bookKeysToCheck = ['title', 'subtitle', 'narrator', 'author', 'publishYear', 'series', 'volumeNumber', 'description', 'language', 'publisher', 'isbn', 'asin']
      var newBook = newAb.book
      var origBook = origAb.book
      var diffObj = {}
      for (const key in newBook) {
        if (bookKeysToCheck.includes(key)) {
          if (newBook[key] !== origBook[key]) {
            if (!diffObj.book) diffObj.book = {}
            diffObj.book[key] = newBook[key]
          }
        }
        if (key === 'genres') {
          if (this.compareStringArrays(newBook[key], origBook[key])) {
            if (!diffObj.book) diffObj.book = {}
            diffObj.book[key] = newBook[key]
          }
        }
      }
      if (newAb.tags && origAb.tags && newAb.tags.join(',') !== origAb.tags.join(',')) {
        diffObj.tags = newAb.tags
      }
      return diffObj
    },
    saveClick() {
      var updates = []
      for (let i = 0; i < this.audiobookCopies.length; i++) {
        var ab = { ...this.audiobookCopies[i] }
        var origAb = ab.originalAudiobook
        delete ab.originalAudiobook

        var res = this.compareAudiobooks(ab, origAb)
        if (res && Object.keys(res).length) {
          updates.push({
            id: ab.id,
            updates: res
          })
        }
      }
      if (!updates.length) {
        return this.$toast.warning('No updates were made')
      }

      console.log('Pushing updates', updates)
      this.isProcessing = true
      this.$axios
        .$post('/api/books/batch/update', updates)
        .then((data) => {
          this.isProcessing = false
          if (data.updates) {
            this.$toast.success(`Successfully updated ${data.updates} audiobooks`)
            this.$router.replace(`/library/${this.currentLibraryId}/bookshelf`)
          } else {
            this.$toast.warning('No updates were necessary')
          }
        })
        .catch((error) => {
          console.error('failed to batch update', error)
          this.$toast.error('Failed to batch update')
          this.isProcessing = false
        })
    },
    applyBatchUpdates() {
      this.audiobookCopies = this.audiobookCopies.map((ab) => {
        if (this.batchDetails.series) ab.book.series = this.batchDetails.series
      })
    }
  },
  mounted() {
    this.init()
  }
}
</script>

<style>
.slide-enter-active,
.slide-leave-active {
  transition: transform 0.2s ease;
}

.slide-enter,
.slide-leave-to {
  transform: translateY(-100%);
  transition: all 150ms ease-in 0s;
}
</style>