<template>
<div class="page-wrapper">
  <el-form inline :model="search">
    <el-form-item label="名称">
      <el-input v-model="search.name" />
    </el-form-item>
    <el-form-item label="所属歌单">
      <el-select v-model="search.libId" multiple collapse-tags>
        <el-option v-for="musicLib in musicLibs" :key="musicLib._id" :value="musicLib._id" :label="musicLib.name" />
      </el-select>
    </el-form-item>
    <el-form-item label="文件类型">
      <el-select v-model="search.ext" multiple >
        <el-option v-for="ext in exts" :key="ext" :value="ext" :label="ext" />
      </el-select>
    </el-form-item>
    <el-form-item label="标题">
      <el-input v-model="search.title" />
    </el-form-item>
    <el-form-item label="唱片集">
      <el-input v-model="search.album" />
    </el-form-item>
    <el-form-item label="艺术家">
      <el-input v-model="search.artist" />
    </el-form-item>
  </el-form>
  <div class="btn-container">
    <el-button type="success" plain icon="VideoPlay" @click="playMusic">播放</el-button>
    <el-button type="primary" icon="Upload" @click="openUploadModal">上传音乐</el-button>
    <div class="search-btn">
      <el-button type="primary" @click="loadDataBase(true)" icon="Search">搜索</el-button>
      <el-button @click="reset" icon="RefreshLeft">重置</el-button>
    </div>
  </div>
  <div class="table-container">
    <el-table :data="musicData" v-loading="loading" stripe @selection-change="dataSelect">
      <el-table-column type="selection" width="55" />
      <el-table-column prop="name" label="名称" show-overflow-tooltip role=""/>
      <el-table-column prop="ext" label="类型" width="100" />
      <el-table-column prop="size" label="文件大小" width="150">
        <template #default="scope">
          {{ prettyBytes(scope.row.size) }}
        </template>
      </el-table-column>
      <el-table-column prop="title" label="标题" show-overflow-tooltip />
      <el-table-column prop="album" label="唱片集" />
      <el-table-column prop="artist" label="艺术家" />
      <el-table-column prop="libId" label="所属歌单" >
        <template #default="scope">
          <template v-if="scope.row.isEditing && currentRow">
            <el-select v-model="currentRow.libId">
              <el-option v-for="musicLib in musicLibs" :key="musicLib._id" :value="musicLib._id" :label="musicLib.name" />
            </el-select>
            <el-button link icon="Check" type="primary" @click="saveMusicLib(scope.row)"></el-button>
            <el-button link icon="Close" type="primary" @click="scope.row.isEditing = false"></el-button>
          </template>
          <template v-else>
            {{ findMusicLib(scope.row.libId) }}
            <el-button link icon="Edit" type="primary" @click="updateLib(scope.row)"></el-button>
          </template>
        </template>
      </el-table-column>
      <el-table-column prop="lyricId" label="歌词" width="120" >
        <template #default="scope">
          <div style="width: 18px">
            <Check v-if="scope.row.lyricId" />
            <Close v-else/>
          </div>
        </template>
      </el-table-column>
      <el-table-column label="操作" width="230" >
        <template #default="scope">
          <el-button link icon="Document" @click="updateLyric(scope.row)" title="歌词"></el-button>
          <el-button link icon="Download" @click="download(scope.row)" title="下载"></el-button>
          <el-button link type="danger" icon="Delete" @click="remove(scope.row)" title="删除"></el-button>
        </template>
      </el-table-column>
    </el-table>
  </div>
  <div class="page-container">
    <el-pagination background 
      :page-sizes="store.state.pageSizeOpts"
      :layout="store.state.pageLayout"
      :current-page="search.pageNum"
      :total="total"
      @size-change="pageSizeChange"
      @current-change="pageChange">
    </el-pagination>
  </div>
  <el-dialog v-model="modifyLyricModal" title="编辑歌词" :width="600" >
    <el-form ref="lyricForm" :model="lyricFormData" :rules="lyricRuleValidate" :label-width="120">
      <el-form-item label="网易云ID" prop="cloudId">
        <el-input v-model="lyricFormData.cloudId" />
      </el-form-item>
      <el-form-item label="名称" prop="name">
        <el-input v-model="lyricFormData.name" />
      </el-form-item>
      <el-form-item label="歌词" prop="lyric">
        <el-input v-model="lyricFormData.lyric" type="textarea" :rows="4"/>
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="modifyLyricModal = false">取消</el-button>
        <el-button type="primary" @click="saveLyric" :loading="modalLoading">确定</el-button>
      </span>
    </template>
  </el-dialog>
  <el-dialog v-model="uploadModal" title="上传音乐" :width="550" @closed="uploadModalClosed" >
    <el-form :label-width="80">
      <el-form-item label="歌单">
        <el-select v-model="libIdSelected">
          <el-option v-for="musicLib in musicLibs" :key="musicLib._id" :value="musicLib._id" :label="musicLib.name" />
        </el-select>
      </el-form-item>
      <el-upload
        ref="musicUpload"
        action="/api/v2/music/upload"
        name="file"
        accept=".mp3,.flac"
        :headers="{token: store.state.loginInfo.token}"
        :on-success="uploadSuccess"
        :on-error="uploadError" 
        :auto-upload="false"
        multiple
        drag
        :data="{libId: libIdSelected}">
        <div class="el-upload__text">
          拖拽到此处或<em>点击上传</em>
        </div>
        <template #tip>
          <div class="el-upload__tip">
            可选择 mp3/flac 文件
          </div>
        </template>
      </el-upload>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="uploadModal = false">取消</el-button>
        <el-button type="primary" @click="uploadMusic" >开始上传</el-button>
      </span>
    </template>
  </el-dialog>
  <el-drawer v-model="musicPlaying" :close-on-click-modal="false" size="40%" title="播放音乐">
    <a-player v-if="musicPlaying" ref="player" autoplay showLrc :list="musicList" v-model:music="currentMusic" @play="musicPlay"/>
  </el-drawer>
</div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { useStore } from 'vuex'
import { useBaseList } from '@/model/baselist'
import { MsgResult, Page } from '@/model/common.dto'
import { UploadInstance, ElMessage, ElMessageBox } from 'element-plus'
import { MusicModel, MusicLibModel, MusicLyricModel, MusicPlayerItem } from '@/model/api/music'
import APlayer from './aplayer/vue-aplayer.vue'
import prettyBytes from 'pretty-bytes'
import type { VForm } from '@/types'
import http from '@/utils/http'

class MusicPage extends Page {
  name?: string
  ext: string[] = []
  title?: string
  album?: string
  artist?: string
  libId?: string[] = []
  reset() {
    super.reset()
    this.name = undefined
    this.ext = []
    this.title = undefined
    this.album = undefined
    this.artist = undefined
    this.libId = []
  }
}

const store = useStore()
const { loading, modalLoading, total, search, setLoadData, loadDataBase, reset, pageChange, pageSizeChange } = useBaseList(new MusicPage())

const currentRow = ref<MusicModel | null>(null)
const libIdSelected = ref<string | null>(null)
const exts = ref<string[]>([])
const musicLibs = ref<MusicLibModel[]>([])
const musicData = ref<MusicModel[]>([])
const uploadModal = ref(false)
const modifyLyricModal = ref(false)
const lyricFormData = ref<MusicLyricModel>({})
const musicPlaying = ref(false)
const musicList = ref<MusicPlayerItem[]>([])
const currentMusic = ref<MusicPlayerItem>()
const lyricForm = ref<VForm>()
const musicUpload = ref<UploadInstance>()
const player = ref<any>()

const lyricRuleValidate = {
  cloudId: [
    { required: true, message: '请输入网易云ID', trigger: 'blur' }
  ],
  name: [
    { required: true, message: '请输入名称', trigger: 'blur' }
  ],
  lyric: [
    { required: true, message: '请输入歌词正文', trigger: 'blur' }
  ],
}

let selectedIds: string[] = []

async function loadData() {
  loading.value = true
  const data = await http.get<MusicPage, any>('/api/v2/music/list', {params: search})
  selectedIds = []
  loading.value = false
  total.value = data.total
  musicData.value = data.data
}
setLoadData(loadData)

function dataSelect(selection: MusicModel[]) {
  selectedIds = selection.map(item => item._id)
}
function findMusicLib(value: string): string | null {
  const musicLib = musicLibs.value.find(item => item._id === value)
  return musicLib ? musicLib.name : null
}
async function playMusic() {
  try {
    const data = await http.get<any, any>('/api/v2/music/list/all', {params: selectedIds.length ? {ids: selectedIds} : search})
    musicList.value = data.map((item: MusicModel, index: number) => {
      const musicItem: MusicPlayerItem = {
        id: index,
        title: item.title || item.name,
        artist: item.artist,
        album: item.album,
        src: `/api/v2/common/music/load/${item._id}`,
        pic: `/api/v2/common/music/album/${item._id}`,
      }
      if (item.lyricId) {
        musicItem.lrc = `${location.origin}/api/v2/common/music/lyric/${item.lyricId}`
      }
      return musicItem
    })
    currentMusic.value = musicList.value[0]
    musicPlaying.value = true
  } catch (err) {
    console.error(err)
    ElMessage.error('获取播放列表失败')
  }
}
function updateLib(row: MusicModel) {
  currentRow.value = { ...row }
  row.isEditing = true
}
function download(row: MusicModel) {
  const link = document.createElement('a')
  link.setAttribute('href', `/api/v2/common/music/load/${row._id}`)
  link.setAttribute('download', row.name)
  link.setAttribute('target', '_blank')
  link.click()
}
function remove(row: MusicModel) {
  ElMessageBox.confirm(`是否确认删除 ${row.name} ？`, '确认删除', {type: 'warning'}).then(async () => {
    const data = await http.delete<{params: {id: string}}, any>('/api/v2/music/delete', {params: {id: row._id}})
    ElMessage.success(data.message)
    loadData()
  }).catch(() => {})
}
async function updateLyric(row: MusicModel) {
  currentRow.value = { ...row }
  modifyLyricModal.value = true
  if (row.lyricId) {
    const data = (await http.get<any, any>('/api/v2/music/lyric/get', {params: {lyricId: row.lyricId}}))
    data.cloudId = data.cloudId ? data.cloudId.toString() : null
    lyricFormData.value = data
  } else {
    lyricFormData.value = {}
  }
}
async function saveLyric() {
  lyricForm.value?.validate(async (valid: boolean) => {
    if (!valid) return
    modalLoading.value = true
    const data = await http.post<MusicLyricModel, any>(`/api/v2/music/lyric/save?musicId=${currentRow.value ? currentRow.value._id : ''}`, lyricFormData.value)
    modalLoading.value = false
    modifyLyricModal.value = false
    ElMessage.success(data.message)
    loadData()
    lyricFormData.value = {}
  })
}
async function saveMusicLib(row: MusicModel) {
  if (!currentRow.value) return
  const data = await http.post<{id: string, libId: string}, any>('/api/v2/music/updateLib', {id: currentRow.value._id, libId: currentRow.value.libId})
  ElMessage.success(data.message)
  row.libId = currentRow.value.libId
  row.isEditing = false
}
function openUploadModal() {
  uploadModal.value = true
  libIdSelected.value = null
}
async function uploadMusic() {
  if (!libIdSelected.value) {
    ElMessage.warning('请选择歌单')
    return
  }
  musicUpload.value?.submit()
}
function uploadSuccess(response: MsgResult) {
  if (response.code === 0) {
    ElMessage.success(response.message)
    loadData()
  } else {
    ElMessage.warning(response.message)
  }
}
function uploadError(error: Error) {
  ElMessage.error(error.message)
}
function uploadModalClosed() {
  musicUpload.value?.clearFiles()
}
function musicPlay() {
  if (!('mediaSession' in window.navigator) || !currentMusic.value) return
  const currentId = currentMusic.value.id
  navigator.mediaSession.metadata = new MediaMetadata({
    title: currentMusic.value.title,
    artist: currentMusic.value.artist,
    album: currentMusic.value.album,
    artwork: [{src: location.origin + currentMusic.value.pic}]
  })
  navigator.mediaSession.setActionHandler('play', () => {
    player.value.play()
  })
  navigator.mediaSession.setActionHandler('pause', () => {
    player.value.pause()
  })
  navigator.mediaSession.setActionHandler('previoustrack', () => {
    if (currentId === 0) {
      player.value.switch(musicList.value.length - 1)
    } else {
      player.value.switch(currentId - 1)
    }
  })
  navigator.mediaSession.setActionHandler('nexttrack', () => {
    if (currentId === musicList.value.length - 1) {
      player.value.switch(0)
    } else {
      player.value.switch(currentId + 1)
    }
  })
}

// created
http.get<never, any>('/api/v2/music/listLibs').then(data => {
  musicLibs.value = data
  loadData()
})
http.get<never, any>('/api/v2/music/listExts').then(data => {
  exts.value = data
})
</script>