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

import UIKit
import CocoaLumberjack

protocol MusicLibraryViewControllerDelegate: class {
	// This is mostly for methods that should probably be abstract... but swift doesn't have those.
	func allMediaItems() -> [IoTMediaItem]
	func optionsForButton() -> [String]
	func doOption(_ option: MusicLibraryOptions) -> Bool // Return true if handled
}

// MARK: -

class MusicLibraryBaseViewController: MiniPlayerEmbeddingViewController {
	weak var delegate: MusicLibraryViewControllerDelegate?
	var playlistHelper: NewUserPlaylistHelper!
	var libraryChangeObserver: ObserverToken?
	
	// MARK: UI Outlets
	@IBOutlet weak var collectionView: UICollectionView?
	@IBOutlet private weak var playAllButton: UIButton?
}

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

		let id = NotificationCenter.default.addObserver(forName: .LocalMusicLibraryCacheInvalidated,
														object: nil,
														queue: OperationQueue.main) { [weak self] (notification) in
															guard let self = self else { return }
															self.handleLibraryInvalidation()
		}

		libraryChangeObserver = ObserverToken(notificationCenter: NotificationCenter.default,
													 token: id)
		
		playlistHelper = NewUserPlaylistHelper(viewController: self, mediaItemProvider: { [weak self] (completion) in
			guard let self = self else {
				completion([])
                return
			}
			
			completion(self.delegate?.allMediaItems() ?? [])
		})
	}
}

// MARK: - UI Actions
extension MusicLibraryBaseViewController {
	@IBAction private func didTapActionsButton(_ sender: UIButton) {
		guard let options = delegate?.optionsForButton() else {
			return
		}
		let alertController = UIAlertController(title: nil,
												message: nil,
												preferredStyle: .actionSheet)
		
		alertController.popoverPresentationController?.sourceView = sender
		alertController.popoverPresentationController?.sourceRect = sender.bounds
		
		let optionAction: (UIAlertAction) -> () = { action in
			guard let title = action.title else {
				return
			}
			
			self.doOption(title)
		}
		for optionIndex in 0..<options.count {
			let option = options[optionIndex]
			alertController.addAction(UIAlertAction(title: option,
													style: .default,
													handler: optionAction))
		}
		
		alertController.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: "Cancel"),
												style: .cancel,
												handler: nil))
		
		self.present(alertController, animated: true)
	}
	
	@IBAction private func playAllTapped(_ sender: AnyObject?) {
		playNow()
	}
}

// MARK: - Public Methods
extension MusicLibraryBaseViewController {
	@objc func handleLibraryInvalidation() {
	}
	
	func doOption(_ title: String) {
		guard let option:MusicLibraryOptions = MusicLibraryOptions.from(string: title) else {
			return
		}

		let handledByDelegate = delegate?.doOption(option) ?? false
		
		if !handledByDelegate {
			switch option {
			case .playNow:
				playNow()
			case .playNext:
				playNext()
			case .addToQueue:
				addToQueue()
			default:
				break
			}
		}
	}
	
	func updatePlayAllButtonText(count: Int) {
		let boldAttrs: [NSAttributedString.Key : Any] = [.font : UIFont.systemFont(ofSize: 16, weight: .bold) as Any,
														 .foregroundColor: UIColor.white]
		let boldText = NSAttributedString(string: "PLAY ALL ", attributes: boldAttrs)
		
		let numberAttrs: [NSAttributedString.Key : Any] = [.font : UIFont.systemFont(ofSize: 16) as Any,
														   .foregroundColor: UIColor.white]
		let formattedStr = String.localizedStringWithFormat("(%d)", count)
		let numberText = NSAttributedString(string: formattedStr, attributes: numberAttrs)
		let str = NSMutableAttributedString()
		str.append(boldText)
		str.append(numberText)
		
		playAllButton?.setAttributedTitle(str, for: .normal)
		playAllButton?.setAttributedTitle(str, for: .highlighted)
		playAllButton?.setAttributedTitle(str, for: .selected)
	}
	
	func showDestructiveAlert(message: String,
                              destructiveOption: String,
                              destructiveAction: @escaping () -> ()) {
        let alert = UIAlertController(title: nil,
                                      message: message,
                                      preferredStyle: .alert)
		alert.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: "Cancel"),
									  style: .cancel,
									  handler: nil))
		
		alert.addAction(UIAlertAction(title: destructiveOption,
									  style: .destructive,
									  handler: { (action) in
										destructiveAction()
		}))
		
		present(alert, animated: true, completion: nil)
	}
	
	func playNow() {
		guard let playlist = playerGroup?.playlist,
			let allItems = delegate?.allMediaItems()else {
				return
		}
		QueueOperationsHelper.sharedInstance.add(toPlaylist: playlist,
												 items: allItems,
												 atEnd: true,
												 playNow: true,
												 completion: nil,
												 completionQueue: nil)
	}
	
	func playNext() {
		guard let playlist = playerGroup?.playlist,
			let allItems = delegate?.allMediaItems()else {
				return
		}
		QueueOperationsHelper.sharedInstance.add(toPlaylist: playlist,
												 items: allItems,
												 atEnd: false,
												 playNow: false,
												 completion: nil,
												 completionQueue: nil)
	}
	
	func addToQueue() {
		guard let playlist = playerGroup?.playlist,
			let allItems = delegate?.allMediaItems()else {
				return
		}
		QueueOperationsHelper.sharedInstance.add(toPlaylist: playlist,
												 items: allItems,
												 atEnd: true,
												 playNow: false,
												 completion: nil,
												 completionQueue: nil)
	}
}

