//
//  MulticastDelegate.swift
//  MVM5G
//
//  Created by Matt Bruce on 3/23/22.
//  Copyright © 2022 Kyle. All rights reserved.
//

import Foundation

public class MulticastDelegate<T> {
    
    // MARK: - Properties
    private class Wrapper {
        weak var delegate: AnyObject?
        
        init(_ delegate: AnyObject) {
            self.delegate = delegate
        }
    }
    
    private var wrappers: [Wrapper] = []
    public var delegates: [T] {
        return wrappers
            .compactMap{ $0.delegate } as! [T]
    }
    
    // MARK: - Actions
    public func add(delegate: T) {
        let wrapper = Wrapper(delegate as AnyObject)
        wrappers.append(wrapper)
    }
    
    public func add(delegates: [T?]){
        for case let delegate? in delegates {
            add(delegate: delegate)
        }
    }
    
    public func remove(delegate: T) {
        guard let index = wrappers.firstIndex(where: {
            $0.delegate === (delegate as AnyObject)
        }) else {
            return
        }
        wrappers.remove(at: index)
    }
    
    public func removeAll(){
        wrappers.removeAll()
    }
    
    public func invokeForEachDelegate(_ handler: (T) -> ()) {
        delegates.forEach { handler($0) }
    }
}
