//
//  HelperBarViewModel.swift
//  RetroArchiOS
//
//  Created by Yoshi Sugawara on 3/1/22.
//  Copyright © 2022 RetroArch. All rights reserved.
//

import Combine

@available(iOS 13, *)
protocol HelperBarViewModelDelegate: AnyObject {
   func setNavigationBarHidden(_ isHidden: Bool)
   func updateNavigationBarItems()
}

@available(iOS 13, *)
class HelperBarViewModel {
   @Published var didInteractWithBar = false
   private var cancellable: AnyCancellable?
   private var timer: DispatchSourceTimer?
   
   weak var delegate: HelperBarViewModelDelegate?
   weak var actionDelegate: HelperBarActionDelegate?
   
   lazy var barItems: [HelperBarItem] = [
      KeyboardBarItem(actionDelegate: actionDelegate),
      MouseBarItem(actionDelegate: actionDelegate),
      LockOrientationBarItem(actionDelegate: actionDelegate)
   ]
   
   var barItemMapping = [UIBarButtonItem: HelperBarItem]()
   
   init(delegate: HelperBarViewModelDelegate? = nil, actionDelegate: HelperBarActionDelegate? = nil) {
      self.delegate = delegate
      self.actionDelegate = actionDelegate
      setupSubscription()
   }
   
   // Create a timer that will hide the navigation bar after 3 seconds if it's not interacted with
   private func setupTimer() {
      timer = DispatchSource.makeTimerSource()
      timer?.setEventHandler(handler: { [weak self] in
         guard let self = self else { return }
         if !self.didInteractWithBar {
            DispatchQueue.main.async { [weak self] in
               self?.didInteractWithBar = false
               self?.delegate?.setNavigationBarHidden(true)
            }
         }
      })
      timer?.schedule(deadline: .now() + .seconds(3))
      timer?.resume()
   }

   // Listen for changes on didInteractWithBar
   private func setupSubscription() {
      cancellable = $didInteractWithBar
         .receive(on: RunLoop.main)
         .sink(receiveValue: { [weak self] didInteract in
            print("didInteract changed to \(didInteract)")
            if didInteract {
               self?.delegate?.setNavigationBarHidden(false)
               self?.timer?.cancel()
               self?.setupTimer()
               self?.didInteractWithBar = false
            }
      })
   }
   
   func createBarButtonItems() -> [UIBarButtonItem] {
      barItemMapping.removeAll()
      return barItems.map{ [weak self] item in
         let barButtonItem = UIBarButtonItem(image: item.image, style: .plain, target: self, action: #selector(self?.didTapBarItem(_:)))
         self?.barItemMapping[barButtonItem] = item
         return barButtonItem
      }
   }
   
   @objc private func didTapBarItem(_ sender: UIBarButtonItem) {
      guard let item = barItemMapping[sender] else { return }
      item.action()
      delegate?.updateNavigationBarItems()
   }
}

