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

import {
    IdentityProperties, MediaProperties, PageProperties, SearchProperties, TrackProperties, RateProperties, SearchEventWithSingleResultType
    
} from "./typings";

const { BsLogCore } = NativeModules;

/**
     * logIdentityEvent are used to log user-related events that represent user register events,
     * user login events and user logout events. SDK will store the userId provided in the identity
     * events and log the remaining events with that userId. So you don't have to provide the userId
     * again. In case of logout event, SDK will auto-erase all of the stored data including the
     * userId. Identity events require 2 main params:
     *
     * @param user_id           is the user id that is using the app, userId should be the id from your
     *                          platform that is assigned to the user.
     * @param identity_action   enum is the identity Action that defines whether the user is logging
     *                          in or a new user or logging out.
     * @param user_properties   is the object for defining the user properties like country, region_state,
     *                          city, experience, language, ... SDK by default provides enums for country names
     *                          and languages along with experience level.
     * @param meta              is to send any other data you want to send with the ingest, can be null.
     * @param updateImmediately is default set to true, you can use that to log events when the app
     *                          goes in the background or closed.
     */
const logIdentityEvent = (properties: IdentityProperties) => {
    if (Platform.OS === 'android') {
        console.log(properties)
        if(properties.user_properties === null){
            BsLogCore.logIdentityEvent(properties.user_id, properties.identity_action, null, null, false)
        }else{
            BsLogCore.logIdentityEvent(properties.user_id, properties.identity_action, JSON.stringify(properties.user_properties), null, false)
        }
    }
}

/**
     * logPageEvent are auto-triggered, but if you want to track any special case then you can use
     * this event to track the page. It needs 3 main params
     *
     * @param content_block     is used to specify the type of module the page is in. Page can be
     *                          in any multiple modules i.e. core, e-commerce, e-learning, ...
     * @param page_path         is for the page path, where the page/screen is inside the code packages.
     * @param page_title        is the page name, the name of the class.
     * @param duration          is the duration (in seconds, integer) the user spent on that page, it is
     *                          ideal to log this event when a user moves to the next page so that you can
     *                          track the time user spent on the page.
     * @param meta              is to send any other data you want to send with the ingest, can be null.
     * @param updateImmediately is default set to true, you can use that to log events when the app
     *                          goes in the background or closed.
     */
const logPageEvent = (properties: PageProperties) => {
    if (Platform.OS === 'android') {
        console.log(properties)
        BsLogCore.logPageEvent(properties.content_block, properties.page_path, properties.page_title, properties.duration, false)
    }
}

/**
     * logMediaEvent can be used to log events regarding media, for logging the user interaction with
     * the media controls. For example video, image, and audio. You can track different interaction
     * events based on your implementation like when the user plays or pauses the video or audio,
     * if they seek the video or audio to a certain time frame or if they watched the video or
     * finished listening to the audio. Params details are as below:
     *
     * @param content_block     is used to specify the type of module the media is in. Media can be
     *                          in any multiple modules i.e. core, e-commerce, e-learning, ...
     * @param media_id          is for the mediaId used in your system, should be a string.
     * @param media_type        enum is for the media type that if it is a video, audio, or image.
     * @param media_action      enum is for the actions performed on the media, it includes play, pause,
     *                          seek and finish. For Image media type the default media action is to play
     *                          which represents image open event. The same will be used if the user swipes
     *                          in a fullscreen image browser.
     * @param time              is the timeframe in milliseconds for the video and audio, this is the
     *                          actual time of the media when the event is triggered.
     * @param media_catalog     is to proc=vide the catalog details about the media in event.
     * @param meta              is to send any other data you want to send with the ingest, can be null.
     * @param updateImmediately is default set to true, you can use that to log events when the app
     *                          goes in the background or closed.
     */
const logMediaEvent = (properties: MediaProperties) => {
    if (Platform.OS === 'android') {
        console.log(properties)
        if(properties.media_catalog === null || properties.media_catalog.length === 0){
            BsLogCore.logMediaEvent(properties.content_block, properties.media_id, properties.media_type, properties.media_action, properties.time, null, null, false)
        }else{
            BsLogCore.logMediaEvent(properties.content_block, properties.media_id, properties.media_type, properties.media_action, properties.time, JSON.stringify(properties.media_catalog), null, false)
        }
    }
}

/**
     * 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)
        BsLogCore.logMediaImpressionEvent(collection_id, JSON.stringify(visibleContent), search_id);
    }
}

/**
     * logSearchEvent can be used with the search query to log search results based on the module
     * context, it is divided into 4 params.
     *
     * logSearchEvent also returns the search ID associated to that search. This search Id needs to
     * be sent with item view events that are a result of the search query to map the user-item
     * view actions for that search.
     *
     * @param content_block     enum is for the module the search is used in the core, e-commerce, e-learning, ...
     * @param query             is for the search query which the user is searching for.
     * @param results_list        is the list of result ids returned in the search, can be an empty list in
     *                          case of no results returned.
     * @param filter            is the filters applied on search, filters should be mapped as a hashmap
     *                          data type with <String, String> format. in case the search does not offer
     *                          any filters you can also send null in place of the filter param.
     * @param page_number        is required to log the the current page of the search result. Pages
     *                          can start from page 1 and move to the number of results that search
     *                          is returning. Default page number is 1.
     *  @param is_new_search       isNewSearch can be used to distinguish if the search is happening
     *                          as a new search or just to update the page number and result ids.
     *                          If [true] then a new search id will be generated and returned in
     *                          the [getSearchId].
     * @param meta              is to send any other data you want to send with the ingest, can be null.
     * @param updateImmediately is default set to true, you can use that to log events when the app
     *                          goes in the background or closed.
     */
const logSearchEvent = async (properties: SearchProperties, _callback : Function) => {
    if(Platform.OS === 'android'){
        console.log(properties)
        const searchId = await BsLogCore.logSearchEvent(properties.content_block, properties.query, JSON.stringify(properties.results_list), 
            Object.fromEntries(properties.filters), properties.page_number, properties.is_new_search, null, false)
        _callback(searchId);
    }
    else{
        _callback("");
    }
}
const logSearchEventWithSingleResultType = async (properties: SearchEventWithSingleResultType, _callback : Function) => {
    if(Platform.OS === 'android'){
        console.log(properties)
        const searchId = await BsLogCore.logSearchEventWithSingleResultType(properties.content_block, properties.query, 
            properties.results_type, JSON.stringify(properties.result_ids), 
            Object.fromEntries(properties.filters), properties.page_number, properties.is_new_search, null, false)
        _callback(searchId);
    }
    else{
        _callback("");
    }
}

/**
     * logTrackEvent is to log user interactions with custom components inside the app. Track events 
     * is required to log events related to UI elements, viewing a list, viewing an item, and also if 
     * user taps on an external link. There are 3 types of track at the moment which included view 
     * list, view the item, and open an external link.
     *
     * @param track_action      is for providing the type of track being logged. For Track events you
     *                          need to set the track type to differentiate among multiple track types.
     *                          TrackType can be viewing a list of elements, tapping an item from the list
     *                          to view more details on that but in such case passing the item id is
     *                          required to log the event.
     * @param item_id           is required to set the item Id for the item being viewed. It is required if
     *                          the track type is view_item. For others, you may skip this.
     * @param meta              is to send any other data you want to send with the ingest, can be null.
     * @param updateImmediately is default set to true, you can use that to log events when the app
     *                          goes in the background or closed.
     */
const logTrackEvent = (properties: TrackProperties) => {
    if(Platform.OS === 'android'){
        console.log(properties)
        BsLogCore.logTrackEvent(properties.track_action, properties.item_id, null, false)
    }
}

/**
     * logRateEvent is required to log events related to providing rate experience for the
     * elements in the app. Rating the order placing experience, rating the course completing
     * experience or rating the overall app.
     *
     * @param content_block     enum is for the module the rate is used in the core, e-commerce, e-learning, ...
     * @param rateValue         is for the providing the value for the rate. Should be in between 0 to 5,
     *                          if there are more elements like 0 to 10, make sure to divide the value by 2.
     * @param type              is for the providing the type of type being rated. By default SDK
     *                          provides enum values for the rate type to log the events base don specific types but
     *                          you can also use string values as well. Below is the function for logging rate type
     *                          using string.Remember to use the same strings as provided in the enums or else the
     *                          event will be discarded.
     * @param subjectId         is required to set the subject Id for the item being rated. It is required
     *                          in all cases, if the app is rated then provide the application id
     * @param meta              is to send any other data you want to send with the ingest, can be null.
     * @param updateImmediately is default set to true, you can use that to log events when the app
     *                          goes in the background or closed.
     */
 const logRateEvent = (properties: RateProperties) => {
    if(Platform.OS === 'android'){
        console.log(properties)
        BsLogCore.logRateEvent(properties.content_block, properties.rate_value, properties.type, properties.subject_id, null, false)
    }
}

/**
     * 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 BsLogCore.getNudgeResponse()
        let [cta_type, nudge_resource_type, nudge_resource_id] = returnedString.split('||')
        _callback(cta_type, nudge_resource_type, nudge_resource_id);
    }
    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 the when it receives one. The in-app
     * nudges will still be auto fetched from the benshi 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 = () => {
    if(Platform.OS === 'android'){
        BsLogCore.showInAppMessage()
    }
}

export default {
    logIdentityEvent,
    logMediaEvent,
    logPageEvent,
    logSearchEvent,
    logSearchEventWithSingleResultType,
    logTrackEvent,
    getNudgeResponse,
    logMediaImpressionEvent,
    logRateEvent,
    showInAppMessage
}