"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.GoogleAnalyticsProvider = void 0;
const uuid_1 = require("uuid");
const ua = require("universal-analytics");
const decorators_1 = require("../../common/decorators");
const _ = require("lodash");
const yok_1 = require("../../common/yok");
class GoogleAnalyticsProvider {
    constructor(clientId, $staticConfig, $analyticsSettingsService, $logger, $proxyService, $config, analyticsLoggingService) {
        this.clientId = clientId;
        this.$staticConfig = $staticConfig;
        this.$analyticsSettingsService = $analyticsSettingsService;
        this.$logger = $logger;
        this.$proxyService = $proxyService;
        this.$config = $config;
        this.analyticsLoggingService = analyticsLoggingService;
    }
    trackHit(trackInfo) {
        return __awaiter(this, void 0, void 0, function* () {
            const sessionId = (0, uuid_1.v4)();
            try {
                yield this.track(this.$config.GA_TRACKING_ID, trackInfo, sessionId);
            }
            catch (e) {
                this.analyticsLoggingService.logData({
                    type: "Error",
                    message: `Unable to track information ${JSON.stringify(trackInfo)}. Error is: ${e}`,
                });
                this.$logger.trace("Analytics exception: ", e);
            }
        });
    }
    getVisitor(gaTrackingId, proxy) {
        this.analyticsLoggingService.logData({
            message: `Initializing Google Analytics visitor for id: ${gaTrackingId} with clientId: ${this.clientId}.`,
        });
        const visitor = ua({
            tid: gaTrackingId,
            cid: this.clientId,
            headers: {
                ["User-Agent"]: this.$analyticsSettingsService.getUserAgentString(`tnsCli/${this.$staticConfig.version}`),
            },
            requestOptions: {
                proxy,
            },
            https: true,
        });
        this.analyticsLoggingService.logData({
            message: `Successfully initialized Google Analytics visitor for id: ${gaTrackingId} with clientId: ${this.clientId}.`,
        });
        return visitor;
    }
    track(gaTrackingId, trackInfo, sessionId) {
        return __awaiter(this, void 0, void 0, function* () {
            const proxySettings = yield this.$proxyService.getCache();
            const proxy = proxySettings && proxySettings.proxy;
            const visitor = this.getVisitor(gaTrackingId, proxy);
            yield this.setCustomDimensions(visitor, trackInfo.customDimensions, sessionId);
            switch (trackInfo.googleAnalyticsDataType) {
                case "pageview":
                    yield this.trackPageView(visitor, trackInfo);
                    break;
                case "event":
                    yield this.trackEvent(visitor, trackInfo);
                    break;
            }
        });
    }
    setCustomDimensions(visitor, customDimensions, sessionId) {
        return __awaiter(this, void 0, void 0, function* () {
            const defaultValues = {
                ["cd1"]: this.$staticConfig.version,
                ["cd6"]: process.version,
                ["cd3"]: this.clientId,
                ["cd2"]: null,
                ["cd9"]: null,
                ["cd4"]: sessionId,
                ["cd5"]: "Unknown",
            };
            customDimensions = _.merge(defaultValues, customDimensions);
            _.each(customDimensions, (value, key) => {
                this.analyticsLoggingService.logData({
                    message: `Setting custom dimension ${key} to value ${value}`,
                });
                visitor.set(key, value);
            });
        });
    }
    trackEvent(visitor, trackInfo) {
        return new Promise((resolve, reject) => {
            visitor.event(trackInfo.category, trackInfo.action, trackInfo.label, trackInfo.value, { p: this.currentPage }, (err) => {
                if (err) {
                    this.analyticsLoggingService.logData({
                        message: `Unable to track event with category: '${trackInfo.category}', action: '${trackInfo.action}', label: '${trackInfo.label}', ` +
                            `value: '${trackInfo.value}' attached page: ${this.currentPage}. Error is: ${err}.`,
                        type: "Error",
                    });
                    reject(err);
                    return;
                }
                this.analyticsLoggingService.logData({
                    message: `Tracked event with category: '${trackInfo.category}', action: '${trackInfo.action}', label: '${trackInfo.label}', value: '${trackInfo.value}' attached page: ${this.currentPage}.`,
                });
                resolve();
            });
        });
    }
    trackPageView(visitor, trackInfo) {
        return new Promise((resolve, reject) => {
            this.currentPage = trackInfo.path;
            const pageViewData = {
                dp: trackInfo.path,
                dt: trackInfo.title,
            };
            visitor.pageview(pageViewData, (err) => {
                if (err) {
                    this.analyticsLoggingService.logData({
                        message: `Unable to track pageview with path '${trackInfo.path}' and title: '${trackInfo.title}' Error is: ${err}.`,
                        type: "Error",
                    });
                    reject(err);
                    return;
                }
                this.analyticsLoggingService.logData({
                    message: `Tracked pageview with path '${trackInfo.path}' and title: '${trackInfo.title}'.`,
                });
                resolve();
            });
        });
    }
}
__decorate([
    (0, decorators_1.cache)()
], GoogleAnalyticsProvider.prototype, "getVisitor", null);
exports.GoogleAnalyticsProvider = GoogleAnalyticsProvider;
yok_1.injector.register("googleAnalyticsProvider", GoogleAnalyticsProvider);
