//
// © 2017-2020 Qualcomm Technologies, Inc. and/or its subsidiaries. All rights reserved.
//

import UIKit
import CocoaLumberjack

class ChooseMusicViewController: MiniPlayerEmbeddingViewController {
	// MARK: Public Properties
	override var playerGroup: IoTPlayerGroup? {
		didSet {
			updateTitle()
		}
	}
	
	// MARK: Private Properties/Types
    @IBOutlet private weak var tableView: UITableView?
	private struct Segues {
		static let showSongs = "showSongs"
		static let showAlbums = "showAlbums"
		static let showArtists = "showArtists"
		static let showGenres = "showGenres"
		static let showPlaylists = "showPlaylists"
		static let showFavorites = "showFavorites"
		static let showInputSources = "showInputSources"
		static let showMediaServers = "showMediaServers"
        static let showServices = "showServices"
	}
    
    private struct Row {
		let id: String?
        var title: String
        var accessibilityTitle: String
        var imagename: String?
    }
    
    private struct Section {
        var cellIdentifier: String
        var title: String?
        var rows: [Row]
    }
	
	private enum CategoriesSectionRowIndexes: Int {
		case artists = 0
		case albums
		case songs
		case genres
		case playlists
    }
    
    // Unfortunately we need to use a literal for the cell identifier twice...
    private let favoritesCellIdentifier = "ScrollingFavoritesTableViewCell"
    private let favoritesSection = Section(cellIdentifier: "ScrollingFavoritesTableViewCell",
                                           title: nil,
                                           rows: [Row(id: "",
                                                      title: "",
                                                      accessibilityTitle: Accessibility.ChooseMusicSourceScreen.Row.favorites,
                                                      imagename: "")])
    
    private let categoriesCellIdentifier = "CategoryTableViewCell"
    private let categoriesSection =
        Section(cellIdentifier: "CategoryTableViewCell",
                title: NSLocalizedString("ON THIS DEVICE", comment: "Section header"),
                rows: [Row(id: "",
                           title: NSLocalizedString("ARTISTS", comment: "Artists text"),
                           accessibilityTitle: Accessibility.ChooseMusicSourceScreen.Row.artists,
                           imagename: "ic-categories-artists"),
                       Row(id: "",
                           title: NSLocalizedString("ALBUMS", comment: "Albums text"),
                           accessibilityTitle: Accessibility.ChooseMusicSourceScreen.Row.albums,
                           imagename: "ic-categories-albums"),
                       Row(id: "",
                           title: NSLocalizedString("SONGS", comment: "Songs text"),
                           accessibilityTitle: Accessibility.ChooseMusicSourceScreen.Row.songs,
                           imagename: "ic-categories-songs"),
                       Row(id: "",
                           title: NSLocalizedString("GENRES", comment: "Genres text"),
                           accessibilityTitle: Accessibility.ChooseMusicSourceScreen.Row.genres,
                           imagename: "ic-categories-genres"),
                       Row(id: "",
                           title: NSLocalizedString("PLAYLISTS", comment: "Playlist text"),
                           accessibilityTitle: Accessibility.ChooseMusicSourceScreen.Row.playlists,
                           imagename: "ic-categories-playlists")])
	
	private let otherSourcesCellIdentifier = "OtherSourcesTableViewCell"
	private let inputSelectorID = "inputSelectorID"
	private let uPnPID = "uPnPID"
    private let servicesID = "servicesID"
	
	private var otherSourcesSection = Section(cellIdentifier: "OtherSourcesTableViewCell",
									  title: NSLocalizedString("OTHER AUDIO SOURCES", comment: "Other sources text"),
									  rows: [])
	
	private let tableViewHeaderHeight:CGFloat = 37.0
	private let headerIdentifier = "ChooseMusicTableViewHeaderView"
    private var sections = [Section] ()
}

// MARK: - Overridden Methods
extension ChooseMusicViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        let nib = UINib(nibName: headerIdentifier, bundle: nil)
        tableView?.register(nib, forHeaderFooterViewReuseIdentifier: headerIdentifier)

		// Accessibility
		tableView?.makeAccessible(Accessibility.ChooseMusicSourceScreen.categoriesList)
    }
	
	override func viewWillAppear(_ animated: Bool) {
		super.viewWillAppear(animated)
		updateTitle()
		
		setUpSections()
		// Do any additional setup after loading the view.
        //tableView?.separatorStyle = .none
		tableView?.reloadData()
	}
	
	override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
		segue.destination.injectDependencies(preferences: preferences,
											 playerController: playerController)
		if let embedding = segue.destination as? MiniPlayerEmbeddingViewController {
			embedding.playerGroup = playerGroup
		}
	}
}


// MARK: - UI Actions
extension ChooseMusicViewController {
	override func unwindNowPlayingOrQueue(segue: UIStoryboardSegue) {
		// DO NOT REMOVE
		setUpSections()
		// Do any additional setup after loading the view.
		tableView?.reloadData()
	}
}

// MARK: - Private Methods
extension ChooseMusicViewController {
    private func updateTitle() {
        guard let name = playerGroup?.displayName.uppercased() else {
            return
        }

        title = name
    }

    private func setUpSections () {
        sections = [Section] ()
        if FavoritesController.sharedInstance.haveFavorites() {
            sections.append(favoritesSection)
        }
        
        sections.append(categoriesSection)
		
		setUpOtherSourcesSection()
        if otherSourcesSection.rows.count > 0 {
            sections.append(otherSourcesSection)
        }
    }
	
	private func setUpOtherSourcesSection() {
		var items = [Row] ()
		
		if UPnPManager.sharedInstance.mediaServers.count > 0 {
			items.append(Row(id: uPnPID,
                             title: NSLocalizedString("Local Media Servers (DLNA)", comment: "DLNA"),
                             accessibilityTitle: Accessibility.ChooseMusicSourceScreen.Row.mediaServers,
                             imagename: ""))
		}

        items.append(Row(id: inputSelectorID,
                         title: NSLocalizedString("Other Input Sources", comment: "Input Selector"),
                         accessibilityTitle: Accessibility.ChooseMusicSourceScreen.Row.otherInputs,
                         imagename: ""))

        items.append(Row(id: servicesID,
                         title: NSLocalizedString("Third Party Services", comment: "Third Party Services"),
                         accessibilityTitle: Accessibility.ChooseMusicSourceScreen.Row.thirdParty,
                         imagename: ""))
		
		otherSourcesSection.rows = items
	}
}

// MARK: - UITableViewDelegate, UITableViewDataSource Conformance
extension ChooseMusicViewController: UITableViewDelegate, UITableViewDataSource {
    func numberOfSections(in tableView: UITableView) -> Int {
        return sections.count
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return sections[section].rows.count
    }
	
	func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
		let section = sections[indexPath.section]
		if section.cellIdentifier == favoritesCellIdentifier {
			return nil
		} else {
			return indexPath
		}
	}
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let section = sections[indexPath.section]
        let row = section.rows[indexPath.row]
        
        switch section.cellIdentifier {
        // It seems we cannot compare the sections directly so we use the identifiers...
        case favoritesCellIdentifier:
            let cell = tableView.dequeueReusableCell(withIdentifier: favoritesCellIdentifier) as! ScrollingFavoritesTableViewCell
			cell.makeAccessible(row.accessibilityTitle)
			cell.selectionStyle = .none
			cell.onFavoriteSelected = { [weak self] mediaItem in
				guard let playlist = self?.playerGroup?.playlist else {
					return
				}
				QueueOperationsHelper.sharedInstance.add(toPlaylist: playlist,
														 item: mediaItem,
														 atEnd: true,
														 playNow: true,
														 completion: nil,
														 completionQueue: nil)
			}
			
			cell.onShowAll = { [weak self] in
				guard let self = self else { return }
				self.performSegue(withIdentifier: Segues.showFavorites, sender: self)
			}
            return cell
        case categoriesCellIdentifier:
            let cell = tableView.dequeueReusableCell(withIdentifier: categoriesCellIdentifier) as! CategoryTableViewCell
            cell.makeAccessible(row.accessibilityTitle)
            cell.titleLabel?.text = row.title
            cell.accessoryType = .disclosureIndicator
            if let imagename = row.imagename {
                cell.categoryImageView?.image = UIImage(named: imagename)
            }
            return cell
        case otherSourcesCellIdentifier:
            let cell = tableView.dequeueReusableCell(withIdentifier: otherSourcesCellIdentifier) as! OtherSourcesTableViewCell
            cell.makeAccessible(row.accessibilityTitle)
            cell.titleLabel?.text = row.title
            cell.accessoryType = .disclosureIndicator
            return cell
        default:
            return UITableViewCell()
        }
    }
	
	func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
		tableView.deselectRow(at: indexPath, animated: true)
		let section = sections[indexPath.section]
		if section.cellIdentifier == categoriesCellIdentifier {
			if let rowType = CategoriesSectionRowIndexes(rawValue: indexPath.row) {
				switch rowType {
				case .artists:
					performSegue(withIdentifier: Segues.showArtists, sender: self)
				case .albums:
					performSegue(withIdentifier: Segues.showAlbums, sender: self)
				case .songs:
					performSegue(withIdentifier: Segues.showSongs, sender: self)
				case .genres:
					performSegue(withIdentifier: Segues.showGenres, sender: self)
				case .playlists:
					performSegue(withIdentifier: Segues.showPlaylists, sender: self)
				}
			}
		} else if section.cellIdentifier == otherSourcesCellIdentifier {
			if let rowID = section.rows[indexPath.row].id {
				if rowID == inputSelectorID {
					performSegue(withIdentifier: Segues.showInputSources, sender: self)
				} else if rowID == uPnPID {
					performSegue(withIdentifier: Segues.showMediaServers, sender: self)
                } else if rowID == servicesID {
                    performSegue(withIdentifier: Segues.showServices, sender: self)
                }
			}
		}
	}
	
	func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
		let s = sections[section]
		guard let title = s.title else {
			return CGFloat.leastNormalMagnitude
		}
		return title.isEmpty ? CGFloat.leastNormalMagnitude : tableViewHeaderHeight
	}
	
    func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
        return CGFloat.leastNormalMagnitude // if we return zero it gets ignored.
    }
    
    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let s = sections[section]
        guard let title = s.title else {
            return nil
        }
        
        if title.isEmpty {
            return nil
        }
        
        guard let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: headerIdentifier) as? ChooseMusicTableViewHeaderView else {
            return nil
        }
        
        header.titleLabel?.text = s.title
        return header
    }
}
