//
//  AnagogEventEmitterManager.swift
//
//  Copyright © 2022 Anagog Ltd. All rights reserved.
//

import Foundation
import JedAIKit
import os

protocol AnagogEventEmitterManagerDelegate {
    var hasListeners: Bool { get }
    func sendEvent(action: EventEmitterAction, payload: Any?)
}

public class AnagogEventEmitterManager {
    
    private var eventsQueue = DispatchQueue(label: "com.anagog.package.pending.events.queue", qos: .utility)
    private var pendingEvents: [(action: EventEmitterAction, payload: Any?)] = []
    
    private var wasConnected: Bool = false
    internal var delegate: AnagogEventEmitterManagerDelegate? = nil
    
    public func sendEvent(_ action: EventEmitterAction, payload: [AnyHashable: Any]?) {
        eventsQueue.sync {
            guard let delegate = prepareToSend() else {
                os_log_file("[package] EventEmitter is not ready. %@ event will be added to the queue", action.rawValue)
                pendingEvents.append((action, payload))
                return
            }
            guard pendingEvents.isEmpty else {
                pendingEvents.append((action, payload))
                return
            }
            delegate.sendEvent(action: action, payload: payload)
        }
    }
    
    internal func checkForSend() {
        guard let delegate = prepareToSend() else {
            return
        }
        
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
            self.eventsQueue.sync {
                if self.wasConnected == false {
                	delegate.sendEvent(action: .onStreamConnected, payload: nil)
                    self.wasConnected = true
                }
                os_log_file("[package] EventEmitter has %d pending event(s)", self.pendingEvents.count)
                while self.pendingEvents.count > 0 {
                    let event = self.pendingEvents.removeFirst()
                    delegate.sendEvent(action: event.action, payload: event.payload)
                }
            }
        }
    }
    
    private func prepareToSend() -> AnagogEventEmitterManagerDelegate? {
        guard let delegate = delegate else {
            os_log_file("[package] EventEmitter not registered yet", type: .fault)
            wasConnected = false
            return nil
        }
        guard delegate.hasListeners == true else {
            os_log_file("[package] EventEmitter there are no listeners yet", type: .fault)
            wasConnected = false
            return nil
        }
        
        return delegate
    }
    
}

public enum EventEmitterAction: String, CaseIterable {
    case onCampaignTriggered
    case onNotificationClick
    case onSnapshotReport
    case onEncodedEnrichmentReport
    case onStreamConnected
    case onJedAIStatusChange
    case onBestMomentEvent
}
