import { AmplitudeEvents } from '../events/amplitudeEvents';
import internalEvents from '../events/internalEvents';
import { AmplitudeEventBase } from '../models/amplitude/AmplitudeEventBase';
import { BaseService } from './abstract/baseService';
import AmplitudeEventHandlers from './AmplitudeEventHandlers';
import amplitudeEventModificationService from './amplitudeEventModificationService';
import connectService from './connectService';
import eventEmitter from './eventEmitter';

class AmplitudeService extends BaseService {
    public static sharedInstance = new AmplitudeService();

    protected logTag: string = 'AmplitudeService';

    private camelCasePropertyExceptions: string[] = ['PromoId'];

    public init() {
        this.setUserProperties();
        for (const event in AmplitudeEvents) {
            if (AmplitudeEvents.hasOwnProperty(event)) {
                eventEmitter.on(AmplitudeEvents[event], (eventData: AmplitudeEventBase) => {
                    AmplitudeEventHandlers[event + 'Handler'](eventData);
                });
            }
        }

        eventEmitter.on(internalEvents.UpdatePointsWidgets, () => {
            this.setUserProperties();
        });
    }

    public sendEventToAmplitude(eventName: string, data: any = null) {
        if (!(window as any).amplitude) {
            return;
        }
        // Camelize properties
        const amplitudeData: { [propertyName: string]: string } = {};
        if (data) {
            amplitudeEventModificationService.modifyEvent(data);
            Object.keys(data).forEach((prop) => {
                amplitudeData[this.addSpacesToProperty(prop)] = this.camelCaseString(data[prop], prop);
            });
        }
        // Log
        this.logInfo(`Tracking Event: "${eventName}" with properties ${JSON.stringify(amplitudeData)}`);

        amplitude.getInstance().logEvent(eventName, amplitudeData);
    }

    private setUserProperties() {
        if (!(window as any).amplitude) {
            return;
        }
        const identify = new amplitude.Identify();
        const user = connectService.currentUser;
        if (user) {
            identify.set('Current Points', user.totalPoints);
        }
        if (connectService.isConnected) {
            identify.setOnce('Has Nonstop', connectService.isConnected);
        }

        amplitude.getInstance().identify(identify);
    }

    private camelCaseString(input: string, propertyName: string) {
        if (typeof input === 'string' && !this.camelCasePropertyExceptions.includes(propertyName)) {
            let wordsArray = input.toLowerCase().split(' ');
            let output = wordsArray.map((word) => {
                if (word.toLowerCase() === 'mvpd') {
                    return 'MVPD';
                }
                return word.charAt(0).toUpperCase() + word.slice(1);
            });

            // special case for live content (US/Eastern and US/Western)
            wordsArray = output.join(' ').split('/');
            output = wordsArray.map((word) => {
                if (word === 'Us') {
                    return word.toUpperCase();
                }
                return word.charAt(0).toUpperCase() + word.slice(1);
            });

            return output.join('/');
        }
        return input;
    }

    private addSpacesToProperty(input: string) {
        if (typeof input === 'string') {
            const wordsArray = input.match(/[A-Z][a-z]+/g);
            if (!wordsArray) {
                return input;
            }
            return wordsArray.join(' ');
        }
        return input;
    }

}

export default AmplitudeService.sharedInstance as AmplitudeService;