/*
 * TrackCollectionFragment.kt
 * Copyright (C) 2009-2021 Ultrasonic developers
 *
 * Distributed under terms of the GNU GPLv3 license.
 */

package org.moire.ultrasonic.fragment

import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.ContextMenu
import android.view.ContextMenu.ContextMenuInfo
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView.AdapterContextMenuInfo
import android.widget.ImageView
import android.widget.ListView
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.Observer
import androidx.lifecycle.viewModelScope
import androidx.navigation.Navigation
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import java.util.Collections
import java.util.Random
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.launch
import org.koin.android.ext.android.inject
import org.moire.ultrasonic.R
import org.moire.ultrasonic.data.ActiveServerProvider.Companion.isOffline
import org.moire.ultrasonic.domain.MusicDirectory
import org.moire.ultrasonic.fragment.FragmentTitle.Companion.getTitle
import org.moire.ultrasonic.fragment.FragmentTitle.Companion.setTitle
import org.moire.ultrasonic.service.CommunicationErrorHandler
import org.moire.ultrasonic.service.MediaPlayerController
import org.moire.ultrasonic.subsonic.DownloadHandler
import org.moire.ultrasonic.subsonic.ImageLoaderProvider
import org.moire.ultrasonic.subsonic.NetworkAndStorageChecker
import org.moire.ultrasonic.subsonic.ShareHandler
import org.moire.ultrasonic.subsonic.VideoPlayer
import org.moire.ultrasonic.util.AlbumHeader
import org.moire.ultrasonic.util.CancellationToken
import org.moire.ultrasonic.util.Constants
import org.moire.ultrasonic.util.EntryByDiscAndTrackComparator
import org.moire.ultrasonic.util.Settings
import org.moire.ultrasonic.util.Util
import org.moire.ultrasonic.view.AlbumView
import org.moire.ultrasonic.view.EntryAdapter
import org.moire.ultrasonic.view.SongView
import timber.log.Timber

/**
 * Displays a group of tracks, eg. the songs of an album, of a playlist etc.
 * TODO: Refactor this fragment and model to extend the GenericListFragment
 */
class TrackCollectionFragment : Fragment() {

    private var refreshAlbumListView: SwipeRefreshLayout? = null
    private var albumListView: ListView? = null
    private var header: View? = null
    private var albumButtons: View? = null
    private var emptyView: TextView? = null
    private var selectButton: ImageView? = null
    private var playNowButton: ImageView? = null
    private var playNextButton: ImageView? = null
    private var playLastButton: ImageView? = null
    private var pinButton: ImageView? = null
    private var unpinButton: ImageView? = null
    private var downloadButton: ImageView? = null
    private var deleteButton: ImageView? = null
    private var moreButton: ImageView? = null
    private var playAllButtonVisible = false
    private var shareButtonVisible = false
    private var playAllButton: MenuItem? = null
    private var shareButton: MenuItem? = null

    private val mediaPlayerController: MediaPlayerController by inject()
    private val downloadHandler: DownloadHandler by inject()
    private val networkAndStorageChecker: NetworkAndStorageChecker by inject()
    private val imageLoaderProvider: ImageLoaderProvider by inject()
    private val shareHandler: ShareHandler by inject()
    private var cancellationToken: CancellationToken? = null

    private val model: TrackCollectionModel by viewModels()
    private val random: Random = Random()

    override fun onCreate(savedInstanceState: Bundle?) {
        Util.applyTheme(this.context)
        super.onCreate(savedInstanceState)
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.select_album, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        cancellationToken = CancellationToken()

        albumButtons = view.findViewById(R.id.menu_album)

        refreshAlbumListView = view.findViewById(R.id.select_album_entries_refresh)
        albumListView = view.findViewById(R.id.select_album_entries_list)

        refreshAlbumListView!!.setOnRefreshListener {
            updateDisplay(true)
        }

        header = LayoutInflater.from(context).inflate(
            R.layout.select_album_header, albumListView,
            false
        )

        model.currentDirectory.observe(viewLifecycleOwner, defaultObserver)
        model.songsForGenre.observe(viewLifecycleOwner, songsForGenreObserver)

        albumListView!!.choiceMode = ListView.CHOICE_MODE_MULTIPLE
        albumListView!!.setOnItemClickListener { parent, theView, position, _ ->
            if (position >= 0) {
                val entry = parent.getItemAtPosition(position) as MusicDirectory.Entry?
                if (entry != null && entry.isDirectory) {
                    val bundle = Bundle()
                    bundle.putString(Constants.INTENT_EXTRA_NAME_ID, entry.id)
                    bundle.putBoolean(Constants.INTENT_EXTRA_NAME_IS_ALBUM, entry.isDirectory)
                    bundle.putString(Constants.INTENT_EXTRA_NAME_NAME, entry.title)
                    bundle.putString(Constants.INTENT_EXTRA_NAME_PARENT_ID, entry.parent)
                    Navigation.findNavController(theView).navigate(
                        R.id.trackCollectionFragment,
                        bundle
                    )
                } else if (entry != null && entry.isVideo) {
                    VideoPlayer.playVideo(requireContext(), entry)
                } else {
                    enableButtons()
                }
            }
        }

        albumListView!!.setOnItemLongClickListener { _, theView, _, _ ->
            if (theView is AlbumView) {
                return@setOnItemLongClickListener false
            }
            if (theView is SongView) {
                theView.maximizeOrMinimize()
                return@setOnItemLongClickListener true
            }
            return@setOnItemLongClickListener false
        }

        selectButton = view.findViewById(R.id.select_album_select)
        playNowButton = view.findViewById(R.id.select_album_play_now)
        playNextButton = view.findViewById(R.id.select_album_play_next)
        playLastButton = view.findViewById(R.id.select_album_play_last)
        pinButton = view.findViewById(R.id.select_album_pin)
        unpinButton = view.findViewById(R.id.select_album_unpin)
        downloadButton = view.findViewById(R.id.select_album_download)
        deleteButton = view.findViewById(R.id.select_album_delete)
        moreButton = view.findViewById(R.id.select_album_more)
        emptyView = TextView(requireContext())

        selectButton!!.setOnClickListener {
            selectAllOrNone()
        }
        playNowButton!!.setOnClickListener {
            playNow(false)
        }
        playNextButton!!.setOnClickListener {
            downloadHandler.download(
                this@TrackCollectionFragment, append = true,
                save = false, autoPlay = false, playNext = true, shuffle = false,
                songs = getSelectedSongs(albumListView)
            )
            selectAll(selected = false, toast = false)
        }
        playLastButton!!.setOnClickListener {
            playNow(true)
        }
        pinButton!!.setOnClickListener {
            downloadBackground(true)
            selectAll(selected = false, toast = false)
        }
        unpinButton!!.setOnClickListener {
            unpin()
            selectAll(selected = false, toast = false)
        }
        downloadButton!!.setOnClickListener {
            downloadBackground(false)
            selectAll(selected = false, toast = false)
        }
        deleteButton!!.setOnClickListener {
            delete()
            selectAll(selected = false, toast = false)
        }

        registerForContextMenu(albumListView!!)
        setHasOptionsMenu(true)
        enableButtons()
        updateDisplay(false)
    }

    val handler = CoroutineExceptionHandler { _, exception ->
        Handler(Looper.getMainLooper()).post {
            context?.let { CommunicationErrorHandler.handleError(exception, it) }
        }
        refreshAlbumListView!!.isRefreshing = false
    }

    private fun updateDisplay(refresh: Boolean) {
        val args = requireArguments()
        val id = args.getString(Constants.INTENT_EXTRA_NAME_ID)
        val isAlbum = args.getBoolean(Constants.INTENT_EXTRA_NAME_IS_ALBUM, false)
        val name = args.getString(Constants.INTENT_EXTRA_NAME_NAME)
        val parentId = args.getString(Constants.INTENT_EXTRA_NAME_PARENT_ID)
        val playlistId = args.getString(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID)
        val podcastChannelId = args.getString(
            Constants.INTENT_EXTRA_NAME_PODCAST_CHANNEL_ID
        )
        val playlistName = args.getString(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME)
        val shareId = args.getString(Constants.INTENT_EXTRA_NAME_SHARE_ID)
        val shareName = args.getString(Constants.INTENT_EXTRA_NAME_SHARE_NAME)
        val genreName = args.getString(Constants.INTENT_EXTRA_NAME_GENRE_NAME)

        val getStarredTracks = args.getInt(Constants.INTENT_EXTRA_NAME_STARRED, 0)
        val getVideos = args.getInt(Constants.INTENT_EXTRA_NAME_VIDEOS, 0)
        val getRandomTracks = args.getInt(Constants.INTENT_EXTRA_NAME_RANDOM, 0)
        val albumListSize = args.getInt(
            Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 0
        )
        val albumListOffset = args.getInt(
            Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, 0
        )

        fun setTitle(name: String?) {
            setTitle(this@TrackCollectionFragment, name)
        }

        fun setTitle(name: Int) {
            setTitle(this@TrackCollectionFragment, name)
        }

        model.viewModelScope.launch(handler) {
            refreshAlbumListView!!.isRefreshing = true

            model.getMusicFolders(refresh)

            if (playlistId != null) {
                setTitle(playlistName!!)
                model.getPlaylist(playlistId, playlistName)
            } else if (podcastChannelId != null) {
                setTitle(getString(R.string.podcasts_label))
                model.getPodcastEpisodes(podcastChannelId)
            } else if (shareId != null) {
                setTitle(shareName)
                model.getShare(shareId)
            } else if (genreName != null) {
                setTitle(genreName)
                model.getSongsForGenre(genreName, albumListSize, albumListOffset)
            } else if (getStarredTracks != 0) {
                setTitle(getString(R.string.main_songs_starred))
                model.getStarred()
            } else if (getVideos != 0) {
                setTitle(R.string.main_videos)
                model.getVideos(refresh)
            } else if (getRandomTracks != 0) {
                setTitle(R.string.main_songs_random)
                model.getRandom(albumListSize)
            } else {
                setTitle(name)
                if (!isOffline() && Settings.shouldUseId3Tags) {
                    if (isAlbum) {
                        model.getAlbum(refresh, id!!, name, parentId)
                    } else {
                        model.getArtist(refresh, id!!, name)
                    }
                } else {
                    model.getMusicDirectory(refresh, id!!, name, parentId)
                }
            }

            refreshAlbumListView!!.isRefreshing = false
        }
    }

    override fun onCreateContextMenu(menu: ContextMenu, view: View, menuInfo: ContextMenuInfo?) {
        super.onCreateContextMenu(menu, view, menuInfo)
        val info = menuInfo as AdapterContextMenuInfo?

        val entry = albumListView!!.getItemAtPosition(info!!.position) as MusicDirectory.Entry?

        if (entry != null && entry.isDirectory) {
            val inflater = requireActivity().menuInflater
            inflater.inflate(R.menu.generic_context_menu, menu)
        }

        shareButton = menu.findItem(R.id.menu_item_share)

        if (shareButton != null) {
            shareButton!!.isVisible = !isOffline()
        }

        val downloadMenuItem = menu.findItem(R.id.menu_download)
        if (downloadMenuItem != null) {
            downloadMenuItem.isVisible = !isOffline()
        }
    }

    override fun onContextItemSelected(menuItem: MenuItem): Boolean {
        Timber.d("onContextItemSelected")
        val info = menuItem.menuInfo as AdapterContextMenuInfo? ?: return true

        val entry = albumListView!!.getItemAtPosition(info.position) as MusicDirectory.Entry?
            ?: return true

        val entryId = entry.id

        when (menuItem.itemId) {
            R.id.menu_play_now -> {
                downloadHandler.downloadRecursively(
                    this, entryId, save = false, append = false,
                    autoPlay = true, shuffle = false, background = false,
                    playNext = false, unpin = false, isArtist = false
                )
            }
            R.id.menu_play_next -> {
                downloadHandler.downloadRecursively(
                    this, entryId, save = false, append = false,
                    autoPlay = false, shuffle = false, background = false,
                    playNext = true, unpin = false, isArtist = false
                )
            }
            R.id.menu_play_last -> {
                downloadHandler.downloadRecursively(
                    this, entryId, save = false, append = true,
                    autoPlay = false, shuffle = false, background = false,
                    playNext = false, unpin = false, isArtist = false
                )
            }
            R.id.menu_pin -> {
                downloadHandler.downloadRecursively(
                    this, entryId, save = true, append = true,
                    autoPlay = false, shuffle = false, background = false,
                    playNext = false, unpin = false, isArtist = false
                )
            }
            R.id.menu_unpin -> {
                downloadHandler.downloadRecursively(
                    this, entryId, save = false, append = false,
                    autoPlay = false, shuffle = false, background = false,
                    playNext = false, unpin = true, isArtist = false
                )
            }
            R.id.menu_download -> {
                downloadHandler.downloadRecursively(
                    this, entryId, save = false, append = false,
                    autoPlay = false, shuffle = false, background = true,
                    playNext = false, unpin = false, isArtist = false
                )
            }
            R.id.select_album_play_all -> {
                // TODO: Why is this being handled here?!
                playAll()
            }
            R.id.menu_item_share -> {
                val entries: MutableList<MusicDirectory.Entry?> = ArrayList(1)
                entries.add(entry)
                shareHandler.createShare(
                    this, entries, refreshAlbumListView,
                    cancellationToken!!
                )
                return true
            }
            else -> {
                return super.onContextItemSelected(menuItem)
            }
        }
        return true
    }

    override fun onPrepareOptionsMenu(menu: Menu) {
        super.onPrepareOptionsMenu(menu)
        playAllButton = menu.findItem(R.id.select_album_play_all)

        if (playAllButton != null) {
            playAllButton!!.isVisible = playAllButtonVisible
        }

        shareButton = menu.findItem(R.id.menu_item_share)

        if (shareButton != null) {
            shareButton!!.isVisible = shareButtonVisible
        }
    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        inflater.inflate(R.menu.select_album, menu)
        super.onCreateOptionsMenu(menu, inflater)
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        val itemId = item.itemId
        if (itemId == R.id.select_album_play_all) {
            playAll()
            return true
        } else if (itemId == R.id.menu_item_share) {
            shareHandler.createShare(
                this, getSelectedSongs(albumListView),
                refreshAlbumListView, cancellationToken!!
            )
            return true
        }

        return false
    }

    override fun onDestroyView() {
        cancellationToken!!.cancel()
        super.onDestroyView()
    }

    private fun playNow(append: Boolean) {
        val selectedSongs = getSelectedSongs(albumListView)

        if (selectedSongs.isNotEmpty()) {
            downloadHandler.download(
                this, append, false, !append, playNext = false,
                shuffle = false, songs = selectedSongs
            )
            selectAll(selected = false, toast = false)
        } else {
            playAll(false, append)
        }
    }

    private fun playAll(shuffle: Boolean = false, append: Boolean = false) {
        var hasSubFolders = false

        for (i in 0 until albumListView!!.count) {
            val entry = albumListView!!.getItemAtPosition(i) as MusicDirectory.Entry?
            if (entry != null && entry.isDirectory) {
                hasSubFolders = true
                break
            }
        }

        val isArtist = requireArguments().getBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, false)
        val id = requireArguments().getString(Constants.INTENT_EXTRA_NAME_ID)

        if (hasSubFolders && id != null) {
            downloadHandler.downloadRecursively(
                this, id, false, append, !append,
                shuffle, background = false, playNext = false, unpin = false, isArtist = isArtist
            )
        } else {
            selectAll(selected = true, toast = false)
            downloadHandler.download(
                this, append, false, !append, false,
                shuffle, getSelectedSongs(albumListView)
            )
            selectAll(selected = false, toast = false)
        }
    }

    private fun selectAllOrNone() {
        var someUnselected = false
        val count = albumListView!!.count

        for (i in 0 until count) {
            if (!albumListView!!.isItemChecked(i) &&
                albumListView!!.getItemAtPosition(i) is MusicDirectory.Entry
            ) {
                someUnselected = true
                break
            }
        }
        selectAll(someUnselected, true)
    }

    private fun selectAll(selected: Boolean, toast: Boolean) {
        val count = albumListView!!.count
        var selectedCount = 0

        for (i in 0 until count) {
            val entry = albumListView!!.getItemAtPosition(i) as MusicDirectory.Entry?
            if (entry != null && !entry.isDirectory && !entry.isVideo) {
                albumListView!!.setItemChecked(i, selected)
                selectedCount++
            }
        }

        // Display toast: N tracks selected / N tracks unselected
        if (toast) {
            val toastResId = if (selected)
                R.string.select_album_n_selected
            else
                R.string.select_album_n_unselected
            Util.toast(activity, getString(toastResId, selectedCount))
        }
        enableButtons()
    }

    private fun enableButtons() {
        val selection = getSelectedSongs(albumListView)
        val enabled = selection.isNotEmpty()
        var unpinEnabled = false
        var deleteEnabled = false

        var pinnedCount = 0

        for (song in selection) {
            if (song == null) continue
            val downloadFile = mediaPlayerController.getDownloadFileForSong(song)
            if (downloadFile.isWorkDone) {
                deleteEnabled = true
            }
            if (downloadFile.isSaved) {
                pinnedCount++
                unpinEnabled = true
            }
        }

        playNowButton!!.visibility = if (enabled) View.VISIBLE else View.GONE
        playNextButton!!.visibility = if (enabled) View.VISIBLE else View.GONE
        playLastButton!!.visibility = if (enabled) View.VISIBLE else View.GONE
        pinButton!!.visibility = if (enabled && !isOffline() && selection.size > pinnedCount)
            View.VISIBLE
        else
            View.GONE
        unpinButton!!.visibility = if (enabled && unpinEnabled) View.VISIBLE else View.GONE
        downloadButton!!.visibility = if (enabled && !deleteEnabled && !isOffline())
            View.VISIBLE
        else
            View.GONE
        deleteButton!!.visibility = if (enabled && deleteEnabled) View.VISIBLE else View.GONE
    }

    private fun downloadBackground(save: Boolean) {
        var songs = getSelectedSongs(albumListView)

        if (songs.isEmpty()) {
            selectAll(selected = true, toast = false)
            songs = getSelectedSongs(albumListView)
        }

        downloadBackground(save, songs)
    }

    private fun downloadBackground(save: Boolean, songs: List<MusicDirectory.Entry?>) {
        val onValid = Runnable {
            networkAndStorageChecker.warnIfNetworkOrStorageUnavailable()
            mediaPlayerController.downloadBackground(songs, save)

            if (save) {
                Util.toast(
                    context,
                    resources.getQuantityString(
                        R.plurals.select_album_n_songs_pinned, songs.size, songs.size
                    )
                )
            } else {
                Util.toast(
                    context,
                    resources.getQuantityString(
                        R.plurals.select_album_n_songs_downloaded, songs.size, songs.size
                    )
                )
            }
        }
        onValid.run()
    }

    private fun delete() {
        var songs = getSelectedSongs(albumListView)

        if (songs.isEmpty()) {
            selectAll(selected = true, toast = false)
            songs = getSelectedSongs(albumListView)
        }

        mediaPlayerController.delete(songs)
    }

    private fun unpin() {
        val songs = getSelectedSongs(albumListView)
        Util.toast(
            context,
            resources.getQuantityString(
                R.plurals.select_album_n_songs_unpinned, songs.size, songs.size
            )
        )
        mediaPlayerController.unpin(songs)
    }

    private val songsForGenreObserver = Observer<MusicDirectory> { musicDirectory ->

        // Hide more button when results are less than album list size
        if (musicDirectory.getChildren().size < requireArguments().getInt(
            Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 0
        )
        ) {
            moreButton!!.visibility = View.GONE
        } else {
            moreButton!!.visibility = View.VISIBLE
        }

        moreButton!!.setOnClickListener {
            val theGenre = requireArguments().getString(Constants.INTENT_EXTRA_NAME_GENRE_NAME)
            val size = requireArguments().getInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 0)
            val theOffset = requireArguments().getInt(
                Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, 0
            ) + size
            val bundle = Bundle()
            bundle.putString(Constants.INTENT_EXTRA_NAME_GENRE_NAME, theGenre)
            bundle.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, size)
            bundle.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, theOffset)

            Navigation.findNavController(requireView())
                .navigate(R.id.trackCollectionFragment, bundle)
        }

        updateInterfaceWithEntries(musicDirectory)
    }

    private val defaultObserver = Observer(this::updateInterfaceWithEntries)

    private fun updateInterfaceWithEntries(musicDirectory: MusicDirectory) {
        val entries = musicDirectory.getChildren()

        if (model.currentListIsSortable && Settings.shouldSortByDisc) {
            Collections.sort(entries, EntryByDiscAndTrackComparator())
        }

        var allVideos = true
        var songCount = 0

        for (entry in entries) {
            if (!entry.isVideo) {
                allVideos = false
            }
            if (!entry.isDirectory) {
                songCount++
            }
        }

        val listSize = requireArguments().getInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 0)

        if (songCount > 0) {
            if (model.showHeader) {
                val intentAlbumName = requireArguments().getString(Constants.INTENT_EXTRA_NAME_NAME)
                val directoryName = musicDirectory.name
                val header = createHeader(
                    entries, intentAlbumName ?: directoryName,
                    songCount
                )
                if (header != null && albumListView!!.headerViewsCount == 0) {
                    albumListView!!.addHeaderView(header, null, false)
                }
            }

            pinButton!!.visibility = View.VISIBLE
            unpinButton!!.visibility = View.VISIBLE
            downloadButton!!.visibility = View.VISIBLE
            deleteButton!!.visibility = View.VISIBLE
            selectButton!!.visibility = if (allVideos) View.GONE else View.VISIBLE
            playNowButton!!.visibility = View.VISIBLE
            playNextButton!!.visibility = View.VISIBLE
            playLastButton!!.visibility = View.VISIBLE

            if (listSize == 0 || songCount < listSize) {
                moreButton!!.visibility = View.GONE
            } else {
                moreButton!!.visibility = View.VISIBLE
                if (requireArguments().getInt(Constants.INTENT_EXTRA_NAME_RANDOM, 0) > 0) {
                    moreButton!!.setOnClickListener {
                        val offset = requireArguments().getInt(
                            Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, 0
                        ) + listSize
                        val bundle = Bundle()
                        bundle.putInt(Constants.INTENT_EXTRA_NAME_RANDOM, 1)
                        bundle.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, listSize)
                        bundle.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, offset)
                        Navigation.findNavController(requireView()).navigate(
                            R.id.trackCollectionFragment, bundle
                        )
                    }
                }
            }
        } else {

            // TODO: This code path can be removed when getArtist has been moved to
            // AlbumListFragment (getArtist returns the albums of an artist)
            pinButton!!.visibility = View.GONE
            unpinButton!!.visibility = View.GONE
            downloadButton!!.visibility = View.GONE
            deleteButton!!.visibility = View.GONE
            selectButton!!.visibility = View.GONE
            playNowButton!!.visibility = View.GONE
            playNextButton!!.visibility = View.GONE
            playLastButton!!.visibility = View.GONE

            if (listSize == 0 || musicDirectory.getChildren().size < listSize) {
                albumButtons!!.visibility = View.GONE
            } else {
                moreButton!!.visibility = View.VISIBLE
            }
        }

        enableButtons()

        val isAlbumList = requireArguments().containsKey(
            Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE
        )

        playAllButtonVisible = !(isAlbumList || entries.isEmpty()) && !allVideos
        shareButtonVisible = !isOffline() && songCount > 0

        albumListView!!.removeHeaderView(emptyView!!)
        if (entries.isEmpty()) {
            emptyView!!.text = getString(R.string.select_album_empty)
            emptyView!!.setPadding(10, 10, 10, 10)
            albumListView!!.addHeaderView(emptyView, null, false)
        }

        if (playAllButton != null) {
            playAllButton!!.isVisible = playAllButtonVisible
        }

        if (shareButton != null) {
            shareButton!!.isVisible = shareButtonVisible
        }

        albumListView!!.adapter = EntryAdapter(
            context,
            imageLoaderProvider.getImageLoader(), entries, true
        )

        val playAll = requireArguments().getBoolean(Constants.INTENT_EXTRA_NAME_AUTOPLAY, false)
        if (playAll && songCount > 0) {
            playAll(
                requireArguments().getBoolean(Constants.INTENT_EXTRA_NAME_SHUFFLE, false),
                false
            )
        }

        model.currentListIsSortable = true
    }

    private fun createHeader(
        entries: List<MusicDirectory.Entry>,
        name: CharSequence?,
        songCount: Int
    ): View? {
        val coverArtView = header!!.findViewById<View>(R.id.select_album_art) as ImageView
        val artworkSelection = random.nextInt(entries.size)
        imageLoaderProvider.getImageLoader().loadImage(
            coverArtView, entries[artworkSelection], false,
            Util.getAlbumImageSize(context)
        )

        val albumHeader = AlbumHeader.processEntries(context, entries)

        val titleView = header!!.findViewById<View>(R.id.select_album_title) as TextView
        titleView.text = name ?: getTitle(this@TrackCollectionFragment) // getActionBarSubtitle());

        // Don't show a header if all entries are videos
        if (albumHeader.isAllVideo) {
            return null
        }

        val artistView = header!!.findViewById<TextView>(R.id.select_album_artist)

        val artist: String = when {
            albumHeader.artists.size == 1 -> albumHeader.artists.iterator().next()
            albumHeader.grandParents.size == 1 -> albumHeader.grandParents.iterator().next()
            else -> resources.getString(R.string.common_various_artists)
        }

        artistView.text = artist

        val genreView = header!!.findViewById<TextView>(R.id.select_album_genre)

        val genre: String = if (albumHeader.genres.size == 1)
            albumHeader.genres.iterator().next()
        else
            resources.getString(R.string.common_multiple_genres)

        genreView.text = genre

        val yearView = header!!.findViewById<TextView>(R.id.select_album_year)

        val year: String = if (albumHeader.years.size == 1)
            albumHeader.years.iterator().next().toString()
        else
            resources.getString(R.string.common_multiple_years)

        yearView.text = year

        val songCountView = header!!.findViewById<TextView>(R.id.select_album_song_count)
        val songs = resources.getQuantityString(
            R.plurals.select_album_n_songs, songCount,
            songCount
        )
        songCountView.text = songs

        val duration = Util.formatTotalDuration(albumHeader.totalDuration)

        val durationView = header!!.findViewById<TextView>(R.id.select_album_duration)
        durationView.text = duration

        return header
    }

    private fun getSelectedSongs(albumListView: ListView?): List<MusicDirectory.Entry?> {
        val songs: MutableList<MusicDirectory.Entry?> = ArrayList(10)

        if (albumListView != null) {
            val count = albumListView.count
            for (i in 0 until count) {
                if (albumListView.isItemChecked(i)) {
                    songs.add(albumListView.getItemAtPosition(i) as MusicDirectory.Entry?)
                }
            }
        }

        return songs
    }
}
