 public struct Subscription<StateType: State> {
     private(set) weak var subscriber: AnySubscriber? = nil
     let selector: ((StateType) -> Any)?
+    let useMainQueue: Bool
 }
 
 


public class Core<StateType: State> {
    
    private var subscriptions = [Subscription<StateType>]()
    private var middlewares = [Middlewares<StateType>]()
    public private (set) var state: StateType {
        didSet {
            subscriptions = subscriptions.filter { $0.subscriber != nil }
            DispatchQueue.main.async {
                for subscription in self.subscriptions {
                    self.publishStateChange(subscriber: subscription.subscriber, selector: subscription.selector)
                }
            }
        }
    }

    
    // MARK: - Subscriptions
    
    public func add(subscriber: AnySubscriber, notifyOnMainQueue: Bool = true, selector: ((StateType) -> Any)? = nil) {
        guard !subscriptions.contains(where: {$0.subscriber === subscriber}) else { return }
        subscriptions.append(Subscription(subscriber: subscriber, selector: selector, useMainQueue: notifyOnMainQueue))
        publishStateChange(subscriber: subscriber, selector: selector, notifyOnMainQueue: notifyOnMainQueue)
    }
    
    public func remove(subscriber: AnySubscriber) {
        subscriptions = subscriptions.filter { $0.subscriber !== subscriber }
    }
    
    private func publishStateChange(subscriber: AnySubscriber?, selector: ((StateType) -> Any)?, notifyOnMainQueue: Bool) {
        let state = self.state
        let queue = notifyOnMainQueue ? DispatchQueue.main : jobQueue
        queue.async {
            if let selector = selector {
                subscriber?._update(with: selector(state))
            } else {
                subscriber?._update(with: state)
            }
        }
    }
    
    // MARK: - Events
    
    public func fire(event: Event) {
        jobQueue.async {
            self.state.react(to: event)
            let state = self.state
            self.middlewares.forEach { $0.middleware._process(event: event, state: state) }
        }
    }
    
    public func fire<C: Command>(command: C) where C.StateType == StateType {
        jobQueue.async {
            command.execute(state: self.state, core: self)
        }
    }
    
}
