//
//  RTNBlazeSdkModule+AppEvents.swift
//  blaze-rtn-sdk
//
//  Created by Reuven Levitsky on 20/02/2024.
//

import Foundation
import BlazeSDK

extension RTNBlazeSdkModule {
    
    enum SupportedAppEvents: String, CaseIterable {
        
        // Global delegate.
        case onErrorThrown = "Blaze.onErrorThrown"
        case onEventTriggered = "Blaze.onEventTriggered"
        
        // Entry point delegate.
        case onDataLoadStarted = "Blaze.onDataLoadStarted"
        case onDataLoadComplete = "Blaze.onDataLoadComplete"
        case onPlayerDidAppear = "Blaze.onPlayerDidAppear"
        case onPlayerDidDismiss = "Blaze.onPlayerDidDismiss"
        case onTriggerCTA = "Blaze.onTriggerCTA"
        case onTriggerPlayerBodyTextLink = "Blaze.onTriggerPlayerBodyTextLink"
        case onPlayerEventTriggered = "Blaze.onPlayerEventTriggered"
        case onTriggerCustomActionButton = "Blaze.onTriggerCustomActionButton"
        case onReadStatusChanged = "Blaze.onReadStatusChanged"
        case onFollowEntityClicked = "Blaze.onFollowEntityClicked"
        case onCastingStateChanged = "Blaze.onCastingStateChanged"
        case onPiPStateChanged = "Blaze.onPiPStateChanged"
    }
    
    struct Constants {
        static let eventDataKey = "eventData"
        static let playerTypeKey = "playerType"
        static let sourceIdKey = "sourceId"
        static let actionTypeKey = "actionType"
        static let actionParamKey = "actionParam"
        static let itemsCountKey = "itemsCount"
        static let playerEventType = "playerEventType"
        static let playerEventParams = "playerEventParams"
        
    }
    
    func createOnEventTriggeredEvent(_ eventData: BlazeSDK.BlazeAnalytics) -> BlazeAppEvent? {
        guard let eventJson = eventData.asJsonString else {
            return nil
        }
        
        let eventData: [String: AnyHashable] = [
            Constants.eventDataKey: eventJson
        ]
        return .init(name: SupportedAppEvents.onEventTriggered.rawValue,
                     body: eventData)
    }
    
    func createOnErrorThrownEvent(_ error: BlazeSDK.BlazeError) -> BlazeAppEvent {
        let eventData: [String: AnyHashable] = [
            "error": error.toReactValue
        ]
        
        return .init(name: SupportedAppEvents.onErrorThrown.rawValue,
                     body: eventData)
    }
    
    func createOnDataLoadStartedEvent(playerType: BlazePlayerType,
                                      sourceId: String?) -> BlazeAppEvent {
        let eventData = EventParamsBuilder.buildDataLoadStartedParams(playerType: playerType, sourceId: sourceId)
        
        return .init(name: SupportedAppEvents.onDataLoadStarted.rawValue,
                     body: eventData)
    }
    
    func createOnDataLoadCompleteEvent(playerType: BlazePlayerType,
                                       sourceId: String?,
                                       itemsCount: Int,
                                       result: BlazeResult) -> BlazeAppEvent {
        let eventData = EventParamsBuilder.buildDataLoadCompletedParams(playerType: playerType, sourceId: sourceId, itemsCount: itemsCount, result: result)
        
        return .init(name: SupportedAppEvents.onDataLoadComplete.rawValue,
                     body: eventData)
    }
    
    func createOnPlayerDidAppearEvent(playerType: BlazePlayerType,
                                      sourceId: String?) -> BlazeAppEvent {
        let eventData = EventParamsBuilder.buildPlayerDidAppearParams(playerType: playerType, sourceId: sourceId)
        
        return .init(name: SupportedAppEvents.onPlayerDidAppear.rawValue,
                     body: eventData)
    }
    
    func createOnPlayerDidDismissEvent(playerType: BlazePlayerType,
                                       sourceId: String?) -> BlazeAppEvent {
        let eventData = EventParamsBuilder.buildPlayerDidDismissParams(playerType: playerType, sourceId: sourceId)
        
        return .init(name: SupportedAppEvents.onPlayerDidDismiss.rawValue,
                     body: eventData)
    }
    
    func createOnTriggerCTAEvent(playerType: BlazePlayerType,
                                 sourceId: String?,
                                 actionType: BlazeCTAActionType,
                                 actionParam: String) -> BlazeAppEvent {
        let eventData = EventParamsBuilder.buildTriggerCTAParams(playerType: playerType, sourceId: sourceId, actionType: actionType, actionParam: actionParam)
        
        return .init(name: SupportedAppEvents.onTriggerCTA.rawValue,
                     body: eventData)
    }
    
    func createOnTriggerPlayerBodyTextLinkEvent(playerType: BlazePlayerType,
                                                sourceId: String?,
                                                actionParam: String) -> BlazeAppEvent {
        let eventData = EventParamsBuilder.buildTriggerPlayerBodyTextLinkParams(playerType: playerType, sourceId: sourceId, actionParam: actionParam)
        
        return .init(name: SupportedAppEvents.onTriggerPlayerBodyTextLink.rawValue,
                     body: eventData)
    }
    
    func createOnPlayerEventTriggeredEvent(playerType: BlazePlayerType,
                                           sourceId: String?,
                                           event: BlazePlayerEvent) -> BlazeAppEvent? {
        guard let eventData = EventParamsBuilder.buildPlayerEventTriggeredParams(playerType: playerType, sourceId: sourceId, event: event) else {
            return nil
        }
        
        return .init(name: SupportedAppEvents.onPlayerEventTriggered.rawValue,
                     body: eventData)
    }
    
    func createOnTriggerCustomActionButtonEvent(playerType: BlazePlayerType,
                                                sourceId: String?,
                                                buttonParams: BlazePlayerCustomActionButtonParams) -> BlazeAppEvent {
        let eventData = EventParamsBuilder.buildTriggerCustomActionButtonParams(playerType: playerType, sourceId: sourceId, buttonParams: buttonParams)
        
        return .init(name: SupportedAppEvents.onTriggerCustomActionButton.rawValue,
                     body: eventData)
    }
    
    func createOnReadStatusChangedEvent(playerType: BlazePlayerType,
                                        sourceId: String?,
                                        dataSourceStringRepresentation: String,
                                        isEntireContentRead: Bool,
                                        itemReadStatus: [String: Bool]) -> BlazeAppEvent {
        let eventData = EventParamsBuilder.buildReadStatusChangedParams(playerType: playerType, sourceId: sourceId, dataSourceStringRepresentation: dataSourceStringRepresentation, isEntireContentRead: isEntireContentRead, itemReadStatus: itemReadStatus)
        
        return .init(name: SupportedAppEvents.onReadStatusChanged.rawValue,
                     body: eventData)
    }

    func createOnFollowEntityClickedEvent(playerType: BlazePlayerType,
                                         sourceId: String?,
                                         newFollowingState: Bool,
                                         followEntityId: String) -> BlazeAppEvent {
        let eventData = EventParamsBuilder.buildFollowEntityClickedParams(playerType: playerType, sourceId: sourceId, newFollowingState: newFollowingState, followEntityId: followEntityId)
        
        return .init(name: SupportedAppEvents.onFollowEntityClicked.rawValue,
                     body: eventData)
    }
    
}

extension BlazePlayerType {
    
    var toReactValue: String? {
        switch self {
        case .moments:
            return "Moments"
        case .stories:
            return "Stories"
        case .videos:
            return "Videos"
        }
    }
    
}

extension BlazeCTAActionType {
    
    var toReactValue: String? {
        switch self {
        case .deeplink:
            return "Deeplink"
        case .web:
            return "Web"
        }
    }
    
}
