import Vue from 'vue' import { reduce, each, union, difference, take, filter, orderBy } from 'lodash' import { secondsToHis } from '../utils' import stub from '../stubs/album' import { songStore, artistStore } from '.' export const albumStore = { stub, cache: [], state: { albums: [stub] }, /** * Init the store. * * @param {Array.} artists The array of artists to extract album data from. */ init (artists) { // Traverse through the artists array and add their albums into our master album list. this.all = reduce(artists, (albums, artist) => { // While we're doing so, for each album, we get its length // and keep a back reference to the artist too. each(artist.albums, album => this.setupAlbum(album, artist)) return albums.concat(artist.albums) }, []) // Then we init the song store. songStore.init(this.all) }, setupAlbum (album, artist) { Vue.set(album, 'playCount', 0) Vue.set(album, 'artist', artist) Vue.set(album, 'info', null) this.getLength(album) this.cache[album.id] = album return album }, /** * Get all albums in the store. * * @return {Array.} */ get all () { return this.state.albums }, /** * Set all albums. * * @param {Array.} value */ set all (value) { this.state.albums = value }, byId (id) { return this.cache[id] }, /** * Get the total length of an album by summing up its songs' duration. * The length will also be converted into a H:i:s format and stored as fmtLength. * * @param {Object} album * * @return {String} The H:i:s format of the album length. */ getLength (album) { Vue.set(album, 'length', reduce(album.songs, (length, song) => length + song.length, 0)) Vue.set(album, 'fmtLength', secondsToHis(album.length)) return album.fmtLength }, /** * Add new album/albums into the current collection. * * @param {Array.|Object} albums */ add (albums) { albums = [].concat(albums) each(albums, album => { this.setupAlbum(album, album.artist) album.playCount = reduce(album.songs, (count, song) => count + song.playCount, 0) }) this.all = union(this.all, albums) }, /** * Add song(s) into an album. * * @param {Object} album * @param {Array.|Object} song */ addSongsIntoAlbum (album, songs) { songs = [].concat(songs) album.songs = union(album.songs || [], songs) each(songs, song => { song.album_id = album.id song.album = album }) album.playCount = reduce(album.songs, (count, song) => count + song.playCount, 0) this.getLength(album) }, /** * Remove song(s) from an album. * * @param {Object} album * @param {Array.|Object} songs */ removeSongsFromAlbum (album, songs) { album.songs = difference(album.songs, [].concat(songs)) album.playCount = reduce(album.songs, (count, song) => count + song.playCount, 0) this.getLength(album) }, /** * Checks if an album is empty. * * @param {Object} album * * @return {boolean} */ isAlbumEmpty (album) { return !album.songs.length }, /** * Remove album(s) from the store. * * @param {Array.|Object} albums */ remove (albums) { albums = [].concat(albums) this.all = difference(this.all, albums) // Remove from the artist as well each(albums, album => { artistStore.removeAlbumsFromArtist(album.artist, album) // Delete the cache while we're here delete this.cache[album.id] }) }, /** * Get top n most-played albums. * * @param {Number} n * * @return {Array.} */ getMostPlayed (n = 6) { // Only non-unknown albums with actually play count are applicable. const applicable = filter(this.all, album => album.playCount && album.id !== 1) return take(orderBy(applicable, 'playCount', 'desc'), n) }, /** * Get n most recently added albums. * * @param {Number} n * * @return {Array.} */ getRecentlyAdded (n = 6) { const applicable = filter(this.all, album => album.id !== 1) return take(orderBy(applicable, 'created_at', 'desc'), n) } }