import {NativeEventEmitter, NativeModules, Platform} from 'react-native';

import {
    ContentBlock,
    CoreCatalogEventType,
    CoreIngestEventType,
    IdentifyProperties,
    MediaCatalog,
    MediaProperties,
    NudgeScreenType,
    PageProperties,
    RateProperties,
    SearchProperties,
    SiteCatalog,
    UserProperties,
} from "./typings";
import {EventsRegistry} from "react-native-navigation/lib/src/events/EventsRegistry";

const {CfLogCore} = NativeModules;

/**
 * logIngestEvent are used to log user-related events that represent user register events,
 * user login events and the rest of the core related events.
 *                          and languages along with experience level.
 * @param eventType         Type of the event tup be sent
 * @param properties        Properties of the Event to be sent
 * @param updateImmediately is default set to true, you can use that to log events when the app
 *                          goes in the background or closed.
 */
const logIngestEvent = (
    eventType: CoreIngestEventType,
    properties: IdentifyProperties | PageProperties | MediaProperties | SearchProperties | RateProperties,
    updateImmediately: boolean = false
) => {
    console.log(properties);
    if (Platform.OS === 'android' || Platform.OS === 'ios') {
        CfLogCore.logIngestEvent(eventType, JSON.stringify(properties), updateImmediately);
    }
};

/**
 * Core catalog values
 *
 * @param catalogType type to the catalog being ingested
 * @param catalogModel Props for the catalog details
 */
const logCatalogEvent = (catalogType: CoreCatalogEventType, catalogModel: UserProperties | SiteCatalog | MediaCatalog) => {
    if (Platform.OS === 'android' || Platform.OS === 'ios') {
        CfLogCore.logCatalogEvent(catalogType, JSON.stringify(catalogModel));
    }
}

/**
 * logMediaImpressionEvent is for the recyclerListView events when you are showing results form a
 * list or from a search and log the impressions on media elements. This will help in logging
 * easily and manages multiple views in a single instance as well
 *
 * @param collection_id         is required to associate the current recycler impression listener to a
 *                              unique UI element.
 * @param visible_item_indices  is the list if current visible elements at any time on a screen, provided
 *                              by {onVisibleIndicesChanged} from the recyclerListView
 * @param content_list          is the mapped list of elements for the impression view to look into.
 *                              This should be mapped with Item Model provided by the SDK.
 * @param search_id             is the for use case when the recyclerListView is for the search results
 *                              and searchId should be the one provided by the search log.
 */
const logMediaImpressionEvent = (collection_id: string, visible_item_indices: any, content_list: any, search_id: string) => {
    if (Platform.OS === 'android') {
        var visibleContent = visible_item_indices.map((x: any) => content_list[x]);
        // console.log(visibleContent)
        CfLogCore.logMediaImpressionEvent(collection_id, JSON.stringify(visibleContent), search_id);
    }
}

/**
 * getNudgeResponse is for following up on the CTA for the nudges for experimentation,
 * it can be to open a product page or adding an element directly to the cart.
 * It can also be to play a video directly on the app from the nudge sent.
 *
 * @param _callback   _callback contains the function to be called when the nudge response
 *                    is parsed to be used by the SDK, function to open a new page or add to cart,
 *                    for details, please see readme or demo app.
 */
const getNudgeResponse = async (_callback: Function) => {
    if (Platform.OS === 'android') {
        let returnedString = await CfLogCore.getNudgeResponse()
        let [cta_type, nudge_resource_type, nudge_resource_id] = returnedString.split('||')
        _callback(cta_type, nudge_resource_type, nudge_resource_id);
    } else if (Platform.OS === 'ios') {
        const event = new NativeEventEmitter(CfLogCore)
        event.addListener('NudgeOnClickEvent', ({nudgeItems}) => {
            let [cta_type, nudge_resource_type, nudge_resource_id] = nudgeItems.split('||')
            _callback(cta_type, nudge_resource_type, nudge_resource_id);
        })
        CfLogCore.getNudgeResponse();
    } else {
        _callback("", "", "");
    }
}

/**
 * showInAppNudge is for showing the in-app message nudge yourself at your own pace and screen.
 * by default the sdk auto triggers the nudge based on when it receives one. The in-app
 * nudges will still be auto fetched from the causalfoundry platform but will be stacked until this
 * function is not called.
 *
 * To make SDK listen for this, make sure to pass false for `setAutoShowInAppNudge` boolean
 * in the init function to false.
 */
const showInAppMessage = (nudgeScreenType: NudgeScreenType) => {
    console.log("showInAppMessage")
    if (Platform.OS === 'android' || Platform.OS === 'ios') {
        console.log("nudgeScreenType: ", nudgeScreenType)
        CfLogCore.showInAppMessage(nudgeScreenType)
    }
}


const uploadAllEvents = () => {
    if (Platform.OS === 'ios') {
        CfLogCore.uploadAllEvents()
    }
}

/**
 * To auto Track page events if you are using the react-native-navigation package. pass the Navigation.events()
 * and the content block for the app.
 *
 * @param NavigationEvent Navigation.events() for the app
 * @param contentBlock content block for the app, default to core.
 */
const setupScreenListener = (NavigationEvent: EventsRegistry, contentBlock: ContentBlock = ContentBlock.Core) => {

    let pageRenderStartTime = 0;
    let pageRenderTime = 0;
    let pageViewStartTime = 0;

    NavigationEvent.registerComponentWillAppearListener(
        ({componentName, componentType}) => {
            if (componentType === 'Component') {
                pageRenderStartTime = Date.now()
            }
        });

    NavigationEvent.registerComponentDidAppearListener(
        ({componentName, componentType}) => {
            if (componentType === 'Component') {
                pageViewStartTime = Date.now()
                pageRenderTime = (pageViewStartTime - pageRenderStartTime)
                if (pageRenderTime <= 0) {
                    pageRenderTime = 0
                } else {
                    pageRenderTime += 50
                }
            }
        });

    NavigationEvent.registerComponentDidDisappearListener(
        ({componentId, componentName, componentType}) => {
            if (componentType === 'Component') {
                let pageDuration = (Date.now() - pageViewStartTime)
                pageDuration /= 1000
                if (pageDuration >= 1) {
                    let pageProperties = {
                        content_block: contentBlock,
                        path: componentId,
                        title: componentName,
                        duration: pageDuration,
                        render_time: pageRenderTime
                    };
                    logIngestEvent(CoreIngestEventType.Page, pageProperties, false);
                }
            }
        });
}

export default {
    logIngestEvent,
    logCatalogEvent,
    getNudgeResponse,
    logMediaImpressionEvent,
    showInAppMessage,
    setupScreenListener,
    uploadAllEvents
}
