//
//  TabController.swift
//  SBrowser
//
//  Created by James Magahern on 7/30/20.
//

import Foundation

protocol TabControllerDelegate: AnyObject {
    func tabController(_ controller: TabController, didUpdateTitle: String, forTab: Tab)
    func tabController(_ controller: TabController, didUpdateFavicon: UIImage?, forTab: Tab)
}

class TabController
{
    @Published var tabs: [Tab] = []
    @Published var activeTabIndex: Int = 0
    
    var policyManager = ResourcePolicyManager()
    weak var controllerDelegate: TabControllerDelegate?
    
    init() {
        // TODO: load tabs from disk.
        _ = createNewTab(url: nil)
    }
    
    func tab(forURL url: URL) -> Tab? {
        tabs.first { $0.url == url }
    }
    
    func tab(forIdentifier identifier: UUID) -> Tab? {
        tabs.first { $0.identifier == identifier }
    }
    
    func tab(forWebView webView: WKWebView) -> Tab? {
        tabs.first { $0.webView == webView }
    }
    
    func createNewTab(url: URL?) -> Tab {
        return self.createNewTab(url: url, webViewConfiguration: nil)
    }
    
    func createNewTab(url: URL?, webViewConfiguration: WKWebViewConfiguration?) -> Tab {
        let tab = Tab(url: url, policyManager: policyManager, webViewConfiguration: webViewConfiguration)
        if tabs.count > 0 {
            tabs.insert(tab, at: activeTabIndex + 1)
        } else {
            tabs.append(tab)
        }
        
        // Title observation
        tab.titleObservation = tab.webView.observe(\.title, changeHandler: { [weak tab, weak self] (webView, change) in
            if let tab = tab, let self = self, let delegate = self.controllerDelegate {
                delegate.tabController(self, didUpdateTitle: webView.title ?? "", forTab: tab)
            }
        })
        
        // Favicon Observation
        tab.faviconObservation = tab.$favicon.receive(on: RunLoop.main).sink { [weak tab, weak self] val in
            if let tab = tab, let self = self, let delegate = self.controllerDelegate {
                delegate.tabController(self, didUpdateFavicon: val, forTab: tab)
            }
        }
        
        return tab
    }
    
    func closeTab(_ tab: Tab) {
        if let index = tabs.firstIndex(of: tab) {
            tabs.remove(at: index)
            
            if tabs.count > 0 {
                if (index - 1) >= 0 {
                    activeTabIndex = index - 1
                } else if index < tabs.count {
                    activeTabIndex = index
                } else {
                    activeTabIndex = tabs.count - 1
                }
            } else {
                _ = createNewTab(url: nil)
                activeTabIndex = 0
            }
        }
    }
}
